﻿#include <QFileDialog>

#include "experimentplateui.h"
#include "ui_experimentplateui.h"
#include "ui_doubleclicked.h"
#include "ui_standard.h"
#include "XmlParser.h"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-escape-sequence"

ExperimentPlateUi::ExperimentPlateUi(QWidget *parent) : QWidget(parent), ui(new Ui::ExperimentPlateUi) {
    ui->setupUi(this);
    this->setMouseTracking(true);

    /* 初始化 */
    startExpe();

    ui->foldSampleList->hide();
    ui->foldTargetList->hide();
    ui->sampleListGap->hide(); // 隐藏快速设置样本下拉框空白
    ui->widget_3->hide(); // 隐藏水平垂直选项

    ui->sample->setView(new QListView());
    ui->target->setView(new QListView());

    // 反应板高级设置页面的按钮提示信息
    ui->importTargetBtn->setToolTip("导入靶基因库新增信息");
    ui->importSampleBtn->setToolTip("导入样本库新增信息");
    ui->deleteTarget->setToolTip("删除选中数据");
    ui->deleteSample->setToolTip("删除选中数据");


    /* 设置文本框输入限制 */
    /* 快速设置：样本名称 */
    QLineEdit *quickSampleNameEdit = ui->sample->lineEdit();
    QRegExp quickSampleNameEditrx("(\\w|-){1,30}");
    QRegExpValidator *quickSampleNameEditReg = new QRegExpValidator(quickSampleNameEditrx, this);
    quickSampleNameEdit->setValidator(quickSampleNameEditReg);
    /* 快速设置：备注 */
    connect(ui->plateComment, &QTextEdit::textChanged, this, [=]() {
        if (ui->plateComment->toPlainText().size() > 500) {
            /* 获取当前光标 */
            QTextCursor cursor = ui->plateComment->textCursor();
            /* 获取当前光标位置 */
            int position = ui->plateComment->textCursor().position();
            /* 限制文本框值 */
            ui->plateComment->setPlainText(ui->plateComment->toPlainText().mid(0, 500));
            /* 设置文本框光标位置 */
            cursor.setPosition(500, QTextCursor::MoveAnchor);
            ui->plateComment->setTextCursor(cursor);
        }
        this->plateRemarks = ui->plateComment->toPlainText();
    });
    /* 高级设置：样本列表样本名列正则校验 */
    QRegExp sampleNamerx("(\\w|-){1,30}");
    ui->sampleList->setItemDelegateForColumn(2, new CustomItemDelegrate(sampleNamerx));
    /* 高级设置：样本列表注释正则校验 */
    QRegExp sampleCommentrx(".{1,30}");
    ui->sampleList->setItemDelegateForColumn(3, new CustomItemDelegrate(sampleCommentrx));
    /* 高级设置：靶基因列表靶基因名校验 */
    QRegExp targetNamerx("(\\w|-){1,30}");
    ui->targetList->setItemDelegateForColumn(2, new CustomItemDelegrate(targetNamerx));
    /* 高级设置：靶基因列表数量校验 */
    QRegExp targetCountrx("^([1-9][0-9]*)(\\.[0-9]*)$|^[1-9][0-9]*$");
    ui->targetList->setItemDelegateForColumn(6, new CustomItemDelegrate(targetCountrx));
    /* 高级设置：靶基因列表备注校验 */
    QRegExp targetCommentrx(".{1,30}");
    ui->targetList->setItemDelegateForColumn(7, new CustomItemDelegrate(targetCommentrx));

    /* 控件信号 */
    connect(ui->gotoDetailTable, &QPushButton::clicked, this, &ExperimentPlateUi::slotGotoDetailTable);
    connect(ui->gotoMaterialTable, &QPushButton::clicked, this, &ExperimentPlateUi::slotGotoMaterialTable);
    connect(ui->gotoTable, &QPushButton::clicked, this, &ExperimentPlateUi::slotGotoTable);
    connect(ui->rightExpending, &QPushButton::clicked, this, &ExperimentPlateUi::slotRightExpanding);
    connect(ui->leftExpending, &QPushButton::clicked, this, &ExperimentPlateUi::slotLeftExpanding);
    connect(ui->restore, &QPushButton::clicked, this, &ExperimentPlateUi::slotRestore);
    connect(ui->foldSampleList, &QPushButton::clicked, this, &ExperimentPlateUi::slotFoldSampleList);
    connect(ui->extendSampleList, &QPushButton::clicked, this, &ExperimentPlateUi::slotExtendSampleList);
    connect(ui->foldTargetList, &QPushButton::clicked, this, &ExperimentPlateUi::slotFoldTargetList);
    connect(ui->extendTargetList, &QPushButton::clicked, this, &ExperimentPlateUi::slotExtendTargetList);

    /* 上一步按钮 */
    connect(ui->previousBtn, &QPushButton::clicked, this, [=]() {
        emit ExperimentPlateUi::previousEvent();
    });

    /* 下一步按钮 */
    connect(ui->nextBtn, &QPushButton::clicked, this, &ExperimentPlateUi::nextCallback);

    /* 保存按钮 */
    connect(ui->saveBtn, &QPushButton::clicked, this, [=]() {
        emit ExperimentPlateUi::saveEvent();
    });

    /* 样板表过滤功能 */
    connect(ui->tableFilter, SIGNAL(triggered(QAction * )), this, SLOT(filter(QAction * )));

    /* 添加样本点 */
    connect(ui->addSampleBtn, &QPushButton::clicked, this, &ExperimentPlateUi::addSample);

    /* 添加靶基因点 */
    connect(ui->addTargetBtn, &QPushButton::clicked, this, &ExperimentPlateUi::addTarget);

    /* 删除样本点 */
    connect(ui->deleteSample, &QPushButton::clicked, this, &ExperimentPlateUi::deleteSample);

    /* 删除靶基因点 */
    connect(ui->deleteTarget, &QPushButton::clicked, this, &ExperimentPlateUi::deleteTarget);

    /* 将样本点数据保存并添加至孔位 */
    connect(ui->sampleList, SIGNAL(itemClicked(QTableWidgetItem * )), this, SLOT(sampleClick(QTableWidgetItem * )));

    /* 将靶基因点数据保存并添加至孔位 */
    connect(ui->targetList, SIGNAL(itemClicked(QTableWidgetItem * )), this, SLOT(targetClick(QTableWidgetItem * )));

//    connect(ui->targetList, &QTableWidget::itemChanged, this, [=](QTableWidgetItem *item) {
//        LOG << "itemChanged";
//        if (item->column() == 6) {
//            ui->targetList->blockSignals(true);
//            this->targetClick(item);
//            ui->targetList->blockSignals(false);
//        }
//    });

    /* 显示孔位中的样本和靶基因信息 */
    connect(ui->sampleTable, &QTableWidget::cellClicked, this, &ExperimentPlateUi::tableClick);

    /* 样本点快速设置 */
    connect(ui->sample, SIGNAL(activated(const int)), this, SLOT(samplebox(const int)));

    /* 靶基因点快速设置 */
    connect(ui->target, SIGNAL(activated(const int)), this, SLOT(targetbox(const int)));

    /* 根据靶基因类型判断数量是否可编辑 */
    connect(ui->targetList, &QTableWidget::cellClicked, this, &ExperimentPlateUi::targetQuantity);

    /* 删除选中孔位的信息 */
    connect(ui->clearTable, &QPushButton::clicked, this, &ExperimentPlateUi::clearTable);

    /* 样板表全屏显示 */
    connect(ui->fullscreen, &QPushButton::clicked, this, &ExperimentPlateUi::slotFullScreen);

    /* 样板表恢复正常大小 */
    connect(ui->normalScreen, &QPushButton::clicked, this, &ExperimentPlateUi::slotNormalScreen);

    /* 弹窗设置功能样板表功能 */
    connect(view, SIGNAL(sampleData(const int)), this, SLOT(sampleSettingBox(const int)));
    connect(view, SIGNAL(targetData(const int)), this, SLOT(targetSettingBox(const int)));

    /* 从样本库导入样本 */
    connect(ui->importSampleBtn, &QPushButton::clicked, this, &ExperimentPlateUi::importSample);

    /* 从染料库导入靶基因 */
    connect(ui->importTargetBtn, &QPushButton::clicked, this, &ExperimentPlateUi::importTarget);

    /* 点击快速设置页重新渲染样本和靶基因下拉框 */
    connect(ui->plateSetup, SIGNAL(tabBarClicked(int)), this, SLOT(rapidComboxChange(int)));

    /* 反应板右键复制功能 */
    connect(actionCopy, &QAction::triggered, this, &ExperimentPlateUi::slotActionCopy);

    /* 反应板右键粘贴功能 */
    connect(actionPaste, &QAction::triggered, this, &ExperimentPlateUi::slotActionPaste);

    /* 反应板右键设置标准品功能 */
    connect(action_setting, &QAction::triggered, this, &ExperimentPlateUi::slotActionSetting);

    /* 反应板右键打印功能 */
    connect(action_print, &QAction::triggered, this, &ExperimentPlateUi::slotActionSave);

    /* 反应板右键导出excel功能 */
    connect(action_export, &QAction::triggered, this, &ExperimentPlateUi::slotActionExport);

    /* 反应板右键功能 */
    connect(ui->sampleTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slot_DL_RcOnTw(QPoint)));

    /* 反应板双击设置功能 */
    connect(ui->sampleTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(doubleClickedTable(int, int)));

    /* 快速设置选择耗材类型 */
    connect(ui->materialType, SIGNAL(activated(const int)), this, SLOT(materialType(const int)));

    /* 快速设置可编辑样本 */
    connect(sampleEdit, &QLineEdit::returnPressed, this, &ExperimentPlateUi::slotSampleEdit);

    /* 标准品设置选择模式 */
    connect(stand->ui->mode, SIGNAL(activated(int)), this, SLOT(slotMode(int)));

    /* 标准品设置靶基因 */
    connect(stand->ui->target, SIGNAL(activated(int)), this, SLOT(slotTarget(int)));

    /* 标准品设置点数 两个信号 */
    connect(stand->ui->countLine, &QLineEdit::returnPressed, this, &ExperimentPlateUi::slotStandCountLine);
    connect(stand->ui->countLine, &QLineEdit::editingFinished, this, &ExperimentPlateUi::slotStandCountLine);

    /* 标准品设置复制品 两个信号 */
    connect(stand->ui->copyLine, &QLineEdit::returnPressed, this, &ExperimentPlateUi::slotStandCopyLine);
    connect(stand->ui->copyLine, &QLineEdit::editingFinished, this, &ExperimentPlateUi::slotStandCopyLine);

    /* 标准品设置起始定量值 两个信号 */
    connect(stand->ui->startLine, &QLineEdit::returnPressed, this, &ExperimentPlateUi::paintStand);
    connect(stand->ui->startLine, &QLineEdit::editingFinished, this, &ExperimentPlateUi::paintStand);

    /* 标准品设置选择安排方式 */
    connect(stand->ui->radioBtn_1, &QRadioButton::clicked, this, &ExperimentPlateUi::slotStandRadioBtn1);
    connect(stand->ui->radioBtn_2, &QRadioButton::clicked, this, &ExperimentPlateUi::slotStandRadioBtn2);

    /* 标准品设置选择孔方式 */
    connect(stand->ui->radioBtn_3, &QPushButton::clicked, this, &ExperimentPlateUi::slotStandRadioBtn3);
    connect(stand->ui->radioBtn_4, &QRadioButton::clicked, this, &ExperimentPlateUi::slotStandRadioBtn4);

    /* 标准品界面显示已选择孔位 */
    connect(stand->ui->tableWidget, &QTableWidget::itemSelectionChanged, this, &ExperimentPlateUi::slotStandShowInfo);

    /* 标准品界面重置功能 */
    connect(stand->ui->newStand, &QPushButton::clicked, this, &ExperimentPlateUi::slotStandNew);

    /* 标准品界面确认功能 */
    connect(stand->ui->confirm, &QPushButton::clicked, this, &ExperimentPlateUi::slotStandConfirm);

    /* 标准品设置稀释比例 */
    connect(stand->ui->yBox, &QComboBox::currentTextChanged, this, &ExperimentPlateUi::paintStand);

    /* 设置反应板高级设置靶基因名不重复 */
    connect(ui->targetList->model(), SIGNAL(dataChanged(QModelIndex, QModelIndex, QVector<int>)), this,
            SLOT(changeTargetName(QModelIndex, QModelIndex, QVector<int>)));
    /*复制计数器*/
    connect(ui->copyCount, SIGNAL(valueChanged(int)), this, SLOT(copystartCountChanged(int)));
    connect(ui->startCount, SIGNAL(valueChanged(int)), this, SLOT(copystartCountChanged(int)));
    /*样本类型表垂直分布 */
    connect(ui->chooseChuizhi, &QRadioButton::clicked, this, &ExperimentPlateUi::copystartCountChanged);
    /*样本类型表垂直分布 */
    connect(ui->chooseShuiping, &QRadioButton::clicked, this, &ExperimentPlateUi::copystartCountChanged);

//    /* 反应板鼠标释放，弹出快速设置样本和靶基因下拉框 */
//    connect(ui->sampleTable, &CustomReactionPlate::repMouseRelease, this, [=](){
//        if(!view->isVisible()){
//            if(ui->plateSetup->currentIndex() == 0){ // 设置页面所在页面为快速设置
//                ui->sampleListGap->show(); // 样本预留空间显示
//                ui->target->showPopup();
//                ui->sample->showPopup();
//                this->sleep(160);
//            }
//        }
//    });



    /* 下拉框隐藏信号 */
    connect(ui->sample, &CustomComboBox::comboBoxHidePopup, this, [=](){
        ui->sampleListGap->hide(); // 样本预留空间隐藏
    });

    /* 参比荧光改变 */
    connect(ui->yingguangLine, &QComboBox::currentTextChanged, this, [=](QString canBi){
        this->canBi = canBi; // 更改参比荧光信息
    });

    connect(view->ui->typeComboBox, SIGNAL(activated(int)), this, SLOT(doubleClickTypeChanged(int)));

    connect(view->ui->countLineEdit, &QLineEdit::returnPressed, this, &ExperimentPlateUi::doubleClickCountChanged);
    connect(view->ui->countLineEdit, &QLineEdit::editingFinished, this, &ExperimentPlateUi::doubleClickCountChanged);
    //    connect(view->ui->typeComboBox, &QComboBox::currentTextChanged, this, [=](QString str) {
    //        LOG << str;
    //    });

    connect(ui->allSelect, &QPushButton::clicked, this, &ExperimentPlateUi::allSelectTarget);

    connect(ui->sampleTable, SIGNAL(entered(QModelIndex)), this, SLOT(ShowTooltip(QModelIndex)));

    connect(ui->sampleTable, &QTableWidget::itemSelectionChanged, this, &ExperimentPlateUi::slotChangeItemsColor);

    connect(ui->sampleTable, &QTableWidget::itemSelectionChanged, this, &ExperimentPlateUi::tableClick);

    // 样本列表样本名修改
    connect(ui->sampleList, &QTableWidget::itemChanged, this, [=](QTableWidgetItem *item) {
        if (item->column() == 2) {
            auto rgb = ui->sampleList->item(item->row(), 1)->background().color().rgb();
            int r = (rgb >> 16) & 0xFF;
            int g = (rgb >> 8) & 0xFF;
            int b = (rgb >> 0) & 0xFF;
            QString color_value = QString::number(r) + "," + QString::number(g) + "," + QString::number(b);
            // LOG << color_value;
            for ( int column = 0; column < 4; column ++) {
                for (int row = 0; row < 8; row ++) {
                    if (reactionPlate.sampleList[column*8 + row].color_value == color_value) {
                        reactionPlate.sampleList[column*8 + row].name = item->text();
                        // LOG << reactionPlate.sampleList[column*8 + row].name << reactionPlate.sampleList[column*8 + row].color_value;
                    }
                }
            }
            updateTable();
            updateSample();
            updateSampleListInfo();
        }
    });

//    // 高级设置靶基因修改数量更改detailTable
//    connect(ui->targetList, &QTableWidget::itemChanged, this, [=](QTableWidgetItem *item) {
//        switch (item->column()) {
//            case 1:
//                LOG << "修改名称";
//                break;
//            case 6:
//                LOG << "修改数量";
//                break;
//            case 7:
//                LOG << "修改注释";
//                break;
//            default:
//                break;
//        }
//    });
}

ExperimentPlateUi::~ExperimentPlateUi() {
    delete ui;
}

/* 下一步 */
void ExperimentPlateUi::nextCallback() {
    LOG << "nextCallback_0";
    // 靶基因所有都为默认配置
    //    ui->targetList->blockSignals(true);
    //    if (ui->targetList->item(0, 6)) this->targetClick(ui->targetList->item(0, 6));
    //    ui->targetList->blockSignals(false);
    emit ExperimentPlateUi::nextEvent();
    LOG << "nextCallback_1";
}

/* 返回数据信息 */
std::tuple<QString, ReactionPlate, QString> ExperimentPlateUi::returnPageInfos() {
    std::tuple<QString, ReactionPlate, QString> reaInfo;
    reaInfo = std::make_tuple(
                this->plateRemarks,
                this->reactionPlate,
                this->canBi
                );

    return reaInfo;
}

/* 发送反应板数据 */
ReactionPlate ExperimentPlateUi::sendReactionPlate() {
    return this->reactionPlate;
}

/**
 * @brief 获取反应板所需数据
 * @param Qstring 反应版备注
 * @param ReactionPlate 反应板数据
 * @param QString 参比荧光
 */
void ExperimentPlateUi::getPlateData(QString plateRemarks, ReactionPlate reactionPlate, QString canBi) {
    this->plateRemarks = plateRemarks;
    this->reactionPlate = reactionPlate;
    this->canBi = canBi;
}

/**
 * @brief 返回反应板孔位是否为空状态
 * @return bool
 */
bool ExperimentPlateUi::hasPlateTargetContent() {
    for (auto &i: this->reactionPlate.targetList) {
        for (int j = 0; j < 4; j++) {
            /* 靶基因 */
            if (i[j].name != "null" &&
                    i[j].name != "") {
                return true;
            }
        }
    }
    return false;
}

/* 高级设置添加样本 */
void ExperimentPlateUi::addSample() {
    // 获取样本行数 并添加一行
    int samplerow = ui->sampleList->rowCount();
    ui->sampleList->setRowCount(samplerow + 1);

    // 添加复选框 并设置为未选中
    QTableWidgetItem *check = new QTableWidgetItem();
    check->setCheckState(Qt::Unchecked);

    // 设置样本名
    QString strname = "Sample" + QString::number(flag[5] + 1);
    QTableWidgetItem *name = new QTableWidgetItem(strname);

    // 设置样本颜色
    QColor qc = selectColor(flag[3], 1);
    QString strcolor;
    QTableWidgetItem *color = new QTableWidgetItem(strcolor);
    color->setBackgroundColor(qc);

    // 设置注释
    QString strExplain = "";
    QTableWidgetItem *explain = new QTableWidgetItem(strExplain);

    // 添加到样本列表
    ui->sampleList->setItem(flag[3], 0, check);
    ui->sampleList->setItem(flag[3], 1, color);
    ui->sampleList->setItem(flag[3], 2, name);
    ui->sampleList->setItem(flag[3], 3, explain);

    // 设置样本颜色不可编辑不可选中
    QTableWidgetItem *item = ui->sampleList->item(flag[3], 1);
    item->setFlags(item->flags() & (~Qt::ItemIsEditable));
    item->setFlags(item->flags() & (~Qt::ItemIsSelectable));

    flag[3]++;
    flag[5]++;

    // 更新快速设置样本
    updateSample();
    // 高级设置: 更新样本面板内容
    updateSampleListInfo();
}

/* 高级设置添加靶基因 */
void ExperimentPlateUi::addTarget() {
    // 存储 报告基因下拉框 与 淬灭基因下拉框的名称
    QList<QString> reporterBox;
    QList<QString> quencherBox;

    // 从配置文件中临时读取 报告基因 与 淬灭基因 存储到下拉框列表中
    for (auto &l: dyeFromConfig) {
        if (l["type"] == "报告基因") {
            reporterBox.append(l["name"]);
        } else if (l["type"] == "淬火基因") {
            quencherBox.append(l["name"]);
        }
    }

    // 如果存在靶基因
    if (ui->targetList->rowCount() > 0) {
        // 获取第一行第三列的报告基因控件，转换为下拉框控件
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, 0, 3);

        // 获取第一行第四列的淬灭基因控件，转换为下拉框控件
        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, 0, 4);

        // 清空报告基因下拉框 与 淬灭基因下拉框 临时变量
        reporterBox.clear();
        quencherBox.clear();
        // 从已存在的靶基因中重新存储报告基因 与 淬灭基因到下拉框列表中
        for (int i = 0; i < combo_reporter->count(); i++) {
            reporterBox.append(combo_reporter->itemText(i));
        }
        for (int i = 0; i < combo_quencher->count(); i++) {
            quencherBox.append(combo_quencher->itemText(i));
        }
    }

    // 获取靶基因行数 并添加一行
    int targetrow = ui->targetList->rowCount();
    ui->targetList->setRowCount(targetrow + 1);

    // 添加复选框 并设置为未选中
    QTableWidgetItem *check = new QTableWidgetItem();
    check->setCheckState(Qt::Unchecked);

    // 设置靶基因名
    QString strname = "Target" + QString::number(flag[4] + 1);

    // 遍历靶基因名列表，如果存在相同的默认名字，则在名字后面+1
    for (const auto &i: targetName) {
        if (strname == i) {
            flag[4]++;
            strname = "Target" + QString::number(flag[4] + 1);
            break;
        }
    }

    // 添加到靶基因名列表
    QTableWidgetItem *name = new QTableWidgetItem(strname);

    targetName.append(strname);


    // 设置报告基因下拉框样式
    QComboBox *reporter = new QComboBox();
    reporter->setStyleSheet(style);
    // 添加报告基因下拉框选项
    for (const auto &m: reporterBox) {
        reporter->addItem(m);
    }


    // 设置淬灭基因下拉框样式
    QComboBox *quencher = new QComboBox();
    quencher->setStyleSheet(style);
    // 添加淬灭基因下拉框选项
    for (const auto &m: quencherBox) {
        quencher->addItem(m);
    }



    // 设置靶基因类型下拉框样式
    QComboBox *type = new QComboBox();
    type->setStyleSheet(style);
    // 添加靶基因类型下拉框选项
    for (const auto &m: targetTypeFromConfig) {
        type->addItem(m);
    }

    // 设置靶基因颜色
    QColor qc = selectColor(flag[2], 2);
    if(reporter->currentText() == "FAM"
            || reporter->currentText() == "SYBR"
            || reporter->currentText() == "Green"){
        qc = selectColor(0, 2); /* 当报告基因为FAM 或SYBR 或Green时为蓝色 */

    }else if(reporter->currentText() == "CY5"
             || reporter->currentText() == "LIZ"){
        qc = selectColor(1, 2); /* 当报告基因为CY5 或LIZ时为红色 */

    }else if(reporter->currentText() == "VIC"
             || reporter->currentText() == "HEX"
             || reporter->currentText() == "JOE"
             || reporter->currentText() == "TET"){
        qc = selectColor(2, 2); /* 当报告基因为VIC或HEX或TET或JOE时为绿色 */
    }else if(reporter->currentText() == "ROX"
             || reporter->currentText() == "TexasRed"){
        qc = selectColor(3, 2); /* 当报告基因为ROX或TexasRed时为黄色 */
    }

    QString strcolor;
    QTableWidgetItem *color = new QTableWidgetItem(strcolor);

    color->setBackgroundColor(qc);

    // 设置靶基因数量
    QTableWidgetItem *quantity = new QTableWidgetItem();
    quantity->setFlags(quantity->flags() & 33);

    // 设置靶基因注释
    QString strexplain;
    QTableWidgetItem *explain = new QTableWidgetItem(strexplain);

    // 添加到靶基因列表
    ui->targetList->setItem(flag[2], 0, check);
    ui->targetList->setItem(flag[2], 1, color);
    ui->targetList->setItem(flag[2], 2, name);
    ui->targetList->setCellWidget(flag[2], 3, reporter);
    ui->targetList->setCellWidget(flag[2], 4, quencher);
    ui->targetList->setCellWidget(flag[2], 5, type);
    ui->targetList->setItem(flag[2], 6, quantity);
    ui->targetList->setItem(flag[2], 7, explain);
    QTableWidgetItem *item = ui->targetList->item(flag[2], 1);
    item->setFlags(item->flags() & (~Qt::ItemIsEditable));
    item->setFlags(item->flags() & (~Qt::ItemIsSelectable));

    flag[2]++;
    flag[4]++;

    // 更新下拉框
    connect(reporter, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateTable(int)));
    connect(quencher, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateTable(int)));
    connect(type, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateTable(int)));

    // 更新快速设置和高级设置的靶基因内容
    updateTarget();
    updateTargetListInfo();
}

/* 高级设置删除样本 */
void ExperimentPlateUi::deleteSample() {
    // 获取被选中的样本列表
    QItemSelectionModel *selection = ui->sampleList->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 存储选中的行号
    QMap<int, int> rowMap;
    foreach(QModelIndex index, indexList) {
        rowMap.insert(index.row(), 0);
    }

    // 创建一个 QMapIterator 对象，用于遍历 QMap
    QMapIterator<int, int> rowMapIterator(rowMap);
    rowMapIterator.toBack(); // 将迭代器移动到 QMap 的末尾
    while (rowMapIterator.hasPrevious()) { // 遍历 QMap
        rowMapIterator.previous();
        int rowToDel = rowMapIterator.key(); // 获取要删除的行号
        QString name = ui->sampleList->item(rowToDel, 2)->text(); // 获取样本名称
        for (int i = 0; i < 96; i++) { // 遍历反应版样本信息
            if (reactionPlate.sampleList[i].name == name) { // 如果找到了与要删除的样本名称相同的样本
                reactionPlate.sampleList[i].name = "null";  // 清空样本内容
                reactionPlate.sampleList[i].color_value = "null";
                reactionPlate.sampleList[i].remarks = "null";
                copySampleName[i] = ""; // 清空复制品信息
            }
        }

        ui->sampleList->removeRow(rowToDel); // 删除选中的行
        flag[3]--;
    }

    // 更新渲染样本视图
    updateTable();
    updateSample();
    markTable();
    //    renderMaterial();
}

/* 高级设置删除靶基因 */
void ExperimentPlateUi::deleteTarget() {
    // 获取被选中的靶基因列表
    QItemSelectionModel *selection = ui->targetList->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 存储选中的行号
    QMap<int, int> rowMap;
    foreach(QModelIndex index, indexList) {
        rowMap.insert(index.row(), 0);
    }

    // 创建一个 QMapIterator 对象，用于遍历 QMap
    QMapIterator<int, int> rowMapIterator(rowMap);
    rowMapIterator.toBack(); // 将迭代器移动到 QMap 的末尾
    while (rowMapIterator.hasPrevious()) { // 遍历 QMap
        rowMapIterator.previous();
        int rowToDel = rowMapIterator.key(); // 获取要删除的行号
        QString name = ui->targetList->item(rowToDel, 2)->text(); // 获取靶基因名称
        for (auto &p: reactionPlate.targetList) {
            for (auto &q: p) {
                // 如果找到了与要删除的靶基因名称相同的靶基因
                if (q.name == name && q.name != "null") {
                    // 清空靶基因内容
                    q.name = "null";
                    q.reporter = "null";
                    q.quencher = "null";
                    q.type = "null";
                    q.quantity = "null";
                    q.color = "null";
                    q.explain = "null";
                    break;
                }
            }
        }
        ui->targetList->removeRow(rowToDel); // 删除选中的行

        targetName.removeAt(rowToDel);
        flag[2]--;
    }
    // 更新和渲染视图
    updateTargetListInfo();
    targetInfoRenderTargetList();
    updateTable();
    updateTarget();
    markTable();
    //    renderMaterial();
}

/* 往反应板添加或去掉样本 */
void ExperimentPlateUi::sampleClick(QTableWidgetItem *item) {
    // 获取被选中的孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();

    // 索引每一个孔位
    foreach(QModelIndex index, indexList) {
        int f = 0; // 单元格勾选状态初始化

        // 设置布局
        widgetLabel = createLabelWidget();

        // 计算选中的孔位编号
        int row = index.row();
        int column = index.column();
        int count = 8 * column + row;

        // 实现单选功能 item是被选中的样本列表
        if (item->column() == 0) { // 判断是否是第一列的单元格
            bool checkStatus = item->checkState();
            if (checkStatus == true) {
                for (int m = 0; m < ui->sampleList->rowCount(); m++) { // 遍历样本列表
                    QTableWidgetItem *check = ui->sampleList->item(m, 0); // 获取每行第一列的单元格
                    bool status = check->checkState(); // 获取单元格的勾选状态
                    if (status == true && m != item->row()) { // 如果单元格被勾选且不是当前行
                        // 将样本列表中的样本设置为未勾选状态
                        ui->sampleList->item(m, 0)->setCheckState(Qt::Unchecked);
                        break;
                    }
                }
            }
        }

        if (item->column() == 0) { // 判断是否是第一列的单元格
            for (int m = 0; m < ui->sampleList->rowCount(); m++) { // 遍历样本列表
                QTableWidgetItem *check = ui->sampleList->item(m, 0); // 获取每行第一列的单元格
                bool status = check->checkState(); // 获取单元格的勾选状态
                if (status == true) { // 如果单元格被勾选
                    // 如果样本名不存在
                    if (ui->sampleList->item(m, 2) == nullptr || ui->sampleList->item(m, 2)->text().isEmpty()) {
                        // 设置反应板样本名为null
                        reactionPlate.sampleList[count].name = "null";
                    } else {
                        // 设置反应板样本名为样本列表中的样本名
                        reactionPlate.sampleList[count].name = ui->sampleList->item(m, 2)->text();
                    }

                    // 如果样本备注不存在
                    if (ui->sampleList->item(m, 3) == nullptr || ui->sampleList->item(m, 3)->text().isEmpty()) {
                        // 设置反应板样本备注为null
                        reactionPlate.sampleList[count].remarks = "null";
                    } else {
                        // 设置反应板样本备注为样本列表中的样本备注
                        reactionPlate.sampleList[count].remarks = ui->sampleList->item(m, 3)->text();
                    }
                    // 设置反应板样本颜色为样本列表中的样本颜色
                    QColor col = ui->sampleList->item(m, 1)->backgroundColor();
                    reactionPlate.sampleList[count].color_value = colorTostring(col);

                    // 下面三个if控制反应板查看按钮的两个样本选项勾选情况
                    // 反应板查看按钮的第一个选项是否是"样本名称"，以及第一个样本名称和第三个选项样本颜色是否被勾选
                    if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                            ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                            ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                        QString name = reactionPlate.sampleList[count].name; // 获取当前位置的样本名称
                        copySampleName[count] = ""; // 清空copySampleName
                        // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                        QLabel *label = createLabel(name);
                        QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                        QString mRgbStr = QString::number(color.rgb(), 16);
                        widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                        vLayout->addWidget(label);
                    }
                    // 反应板查看按钮的第一个选项是否是"样本名称"，第一个样本名称被勾选 并且 第三个选项样本颜色没有被勾选
                    if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                            ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                            ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
                        // 获取反应板的样本列表中第count个样本的名称
                        QString name = reactionPlate.sampleList[count].name;
                        // 清空copySampleName
                        copySampleName[count] = "";
                        // 如果样本名称不是"null"
                        if (name != "null") {
                            // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                            QLabel *label = createLabel(name);
                            // 将标签添加到垂直布局中
                            vLayout->addWidget(label);
                        }
                    }
                    // 反应板查看按钮的第一个选项是否是"样本名称"，第一个样本名称未被勾选 并且 第三个选项样本颜色被勾选
                    if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                            ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                            ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                        // 获取反应板的样本列表中第count个样本的名称
                        QString name = reactionPlate.sampleList[count].name;
                        // 清空copySampleName
                        copySampleName[count] = "";
                        // 如果样本名称不是"null"
                        if (name != "null") {
                            // 创建一个标签对象
                            QLabel *label = new QLabel();
                            // 获取反应板的样本列表中第count个样本的颜色值，并转换为QColor对象
                            QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                            QString mRgbStr = QString::number(color.rgb(), 16);
                            widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                            // 将标签添加到垂直布局中
                            vLayout->addWidget(label);
                        }
                    }
                    f = 1; // 单元格被勾选
                }
            }

            if (f == 0) { // 单元格没被勾选 设置反应板为空
                reactionPlate.sampleList[count].name = "null";
                reactionPlate.sampleList[count].remarks = "null";
                reactionPlate.sampleList[count].color_value = "null";
            }

            int p = 0; // 控制反应板布局
            for (int l = 0; l < 20; l++) {
                // 如果表格过滤器的第二个菜单项的提示是"靶基因"，并且它被选中了
                if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                        ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
                    // 如果反应板的列表中第count个样本的第l个靶基因的报告基因不是"null"
                    if (reactionPlate.targetList[count][l].reporter != "null") {
                        createTargetLabel(reactionPlate, count, l, p, false);
                    }
                }
            }
            // 设置反应板布局
            gLayout->setMargin(0);
            gLayout->setSpacing(0);
            vLayout->addLayout(gLayout);
            // 设置反应板孔位
            ui->sampleTable->setCellWidget(row, column, widgetLabel);
        }
    }
    // 更新和渲染视图
    updateSample();
    markTable();
    renderDetailTable();

}

/*
 *  好像是这两个函数
 *  */

/* 往反应板添加或去掉靶基因 */
void ExperimentPlateUi::targetClick(QTableWidgetItem *item) {
    // 获取被选中的孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 验证是否已添加报告基因
    int b = 0;
    // 定义一个数组，用于存储颜色的三个分量
    int color[3];
    // 判断点击的是否是颜色列
    if (item->column() == 1) {
        // 弹出一个颜色对话框，让用户选择一个颜色，初始颜色为黑色
        QColor c = QColorDialog::getColor(Qt::black, this);
        // 如果用户没有选择有效的颜色，就返回
        if (!c.isValid()) return;
        // 定义三个变量，用于存储颜色的红、绿、蓝分量
        int r, g, b;
        // 定义一个字符串，用于设置背景样式
        QString styleSheet = "background: ";
        // 存储用户选择的颜色
        r = c.red();
        g = c.green();
        b = c.blue();
        color[0] = r;
        color[1] = g;
        color[2] = b;
        // 定义一个QColor对象，用于表示目标颜色
        QColor targetColor;
        targetColor.setRed(color[0]);
        targetColor.setGreen(color[1]);
        targetColor.setBlue(color[2]);
        // 设置靶基因颜色
        QString strcolor;
        QTableWidgetItem *colorItem = new QTableWidgetItem(strcolor);
        colorItem->setBackgroundColor(targetColor);
        ui->targetList->setItem(item->row(), 1, colorItem);
    }

    // 索引孔位
    foreach(QModelIndex index, indexList) {
        int p = 0; // 记录并清除多余的孔位信息

        // 设置布局
        widgetLabel = createLabelWidget();

        // 获取反应板孔位的行号和列号
        int row = index.row();
        int column = index.column();
        // 计算反应板对应孔位的位置编号
        int count = 8 * column + row;

        // 判断点击的单元格是否是第一列
        if (item->column() == 0) {
            // 如果复选框被选中
            bool checkstatus = item->checkState();
            if (checkstatus == true) {
                // 遍历靶基因20个元素
                for (int m = 0; m < 20; m++) {
                    // 如果反应板靶基因的报告基因不为空，执行以下操作
                    if (reactionPlate.targetList[count][m].reporter != "null") {
                        // 获取靶基因中的报告基因名字
                        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, item->row(), 3);
                        QString string_reporter = combo_reporter->currentText();
                        // 如果反应板中的报告基因和靶基因中报告基因的文本相同，
                        // 并且反应板中的靶基因名字和靶基因中的靶基因名字不相同，执行以下操作
                        if (reactionPlate.targetList[count][m].reporter == string_reporter &&
                                reactionPlate.targetList[count][m].name !=
                                ui->targetList->item(item->row(), 2)->text()) {
                            // 验证是否已添加报告基因
                            if (b == 0) {
                                // 弹出一个自定义消息框，提示用户该报告基因已经添加
                                cusMsg->show(this, CMsg::CWarning, "提示", "该报告基因已经添加");
                                b++;
                            }

                            // 将复选框设置为未选中状态
                            item->setCheckState(Qt::Unchecked);
                            break;
                        }
                    }
                }
            }
        }

        int a = 0; // 验证反应板中的报告基因和靶基因中报告基因的文本相同
        if (item->column() == 0) {
            for (int m = 0; m < ui->targetList->rowCount(); m++) {
                QTableWidgetItem *check = ui->targetList->item(m, 0);
                bool status = check->checkState();
                if (status == true) { // 如果靶基因复选框被选中
                    if (ui->targetList->item(m, 2) == nullptr || ui->targetList->item(m, 2)->text().isEmpty()) {
                        // 如果靶基因名字为空，将反应板靶基因名字设置为null
                        reactionPlate.targetList[count][p].name = "null";
                    } else {
                        // 如果靶基因名字不为空，将反应板靶基因名字设置为靶基因名字
                        reactionPlate.targetList[count][p].name = ui->targetList->item(m, 2)->text();
                    }
                    // 获取靶基因中的报告基因名字
                    QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, m, 3);
                    QString string_reporter = combo_reporter->currentText();

                    // 遍历靶基因
                    for (int j = 0; j < p; j++) {
                        // 如果反应板中的报告基因和靶基因中报告基因的文本相同，
                        if (reactionPlate.targetList[count][j].reporter == string_reporter) {
                            // 验证是否已添加报告基因
                            if (b == 0) {
                                cusMsg->show(this, CMsg::CWarning, "提示", "该报告基因已经添加");
                                b++;
                            }

                            // 将反应板靶基因名字设置为null
                            reactionPlate.targetList[count][p].reporter = "null";
                            // 将靶基因复选框设置为未选中状态
                            check->setCheckState(Qt::Unchecked);
                            a = 1;
                            break;
                        }
                    }
                    // 如果反应板中的报告基因和靶基因中报告基因的文本不相同
                    if (a == 0) {
                        // 将反应板靶基因名字设置为靶基因名字
                        reactionPlate.targetList[count][p].reporter = string_reporter;
                    }

                    // 设置淬灭基因和样本类型
                    QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, m, 4);
                    QString string_quencher = combo_quencher->currentText();
                    reactionPlate.targetList[count][p].quencher = string_quencher;

                    QComboBox *combo_type = getComboBoxFromTable(ui->targetList, m, 5);
                    QString string_type = combo_type->currentText();
                    reactionPlate.targetList[count][p].type = string_type;

                    // 设置靶基因数量和注释
                    if (ui->targetList->item(m, 6) == nullptr || ui->targetList->item(m, 6)->text().isEmpty()) {
                        reactionPlate.targetList[count][p].quantity = "null";
                    } else {
                        reactionPlate.targetList[count][p].quantity = ui->targetList->item(m, 6)->text();
                    }

                    if (ui->targetList->item(m, 7) == nullptr || ui->targetList->item(m, 7)->text().isEmpty()) {
                        reactionPlate.targetList[count][p].explain = "null";
                    } else {
                        reactionPlate.targetList[count][p].explain = ui->targetList->item(m, 7)->text();
                    }

                    // 设置靶基因颜色
                    QColor col = ui->targetList->item(m, 1)->backgroundColor();
                    reactionPlate.targetList[count][p].color = colorTostring(col);

                    p++;
                }
            }
            // 记录并清除多余的孔位信息
            for (int l = p; l < 20; l++) {
                reactionPlate.targetList[count][l].name = "null";
                reactionPlate.targetList[count][l].reporter = "null";
                reactionPlate.targetList[count][l].quencher = "null";
                reactionPlate.targetList[count][l].type = "null";
                reactionPlate.targetList[count][l].quantity = "null";
                reactionPlate.targetList[count][l].color = "null";
                reactionPlate.targetList[count][l].explain = "null";
            }


            // 如果反应板中的样本名字不为空
            if (reactionPlate.sampleList[count].name != "null") {
                // 如果反应板查看按钮第一个为样本名称
                // 并且第一个和第三个选项被选中
                if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                        ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                        ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                    // 获取反应板中的样本名字
                    QString name = reactionPlate.sampleList[count].name;
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    // 调用createLabel函数，传入报告基因作为参数，得到一个标签对象
                    QLabel *label = createLabel(name);
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    vLayout->addWidget(label);
                }
                // 如果反应板查看按钮第一个为样本名称
                // 并且第一个选项被选中 第三个选项未被选中
                if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                        ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                        ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
                    // 获取反应板中的样本名字
                    QString name = reactionPlate.sampleList[count].name;

                    // 如果反应板中的样本名字不为空
                    if (name != "null") {
                        if (copySampleName[count] != "") {
                            name = copySampleName[count];
                        }
                        // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                        QLabel *label = createLabel(name);
                        // 将标签添加到垂直布局中
                        vLayout->addWidget(label);
                    }
                }
                // 如果反应板查看按钮第一个为样本名称
                // 并且第一个选项未被选中 第三个选项被选中
                if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                        ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                        ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                    // 获取反应板中的样本名字
                    QString name = reactionPlate.sampleList[count].name;

                    // 如果反应板中的样本名字不为空
                    if (name != "null") {
                        if (copySampleName[count] != "") {
                            name = copySampleName[count];
                        }
                        // 设置样本颜色样式
                        QLabel *label = new QLabel();
                        QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                        QString mRgbStr = QString::number(color.rgb(), 16);
                        widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                        vLayout->addWidget(label);
                    }
                }

            }

            int p = 0; // 调整布局
            for (int l = 0; l < 20; l++) { // 遍历反应板靶基因
                // 如果反应板查看按钮第二个为靶基因
                // 并且第二个选项被选中
                if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                        ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
                    // 如果反应板中的报告基因不为空
                    if (reactionPlate.targetList[count][l].reporter != "null") {
                        createTargetLabel(reactionPlate, count, l, p, false);
                    }
                }

            }

            // 设置反应板样本表格样式
            gLayout->setMargin(0);
            gLayout->setSpacing(0);
            vLayout->addLayout(gLayout);
            ui->sampleTable->setCellWidget(row, column, widgetLabel);
        }

    }

    // 更新渲染视图
    slotUpdateTable(1);
    updateTarget();
    markTable();
    renderDetailTable();

}

/* 在高级设置和快速设置中标出孔位信息 */
void ExperimentPlateUi::tableClick() {
    QString comboBoxSS = "QComboBox {"
                         "font-size: 22px;"
                         "font-family: 'Alibaba PuHuiTi';"
                         "background: transparent;"
                         "border: 1px solid #000;"
                         "padding: 5px;"
                         "}"
                         "QComboBox QAbstractItemView {"
                         "background: #fff;"
                         "border: 1px solid #000;"
                         "}"
                         "QComboBox QAbstractItemView::item {"
                         "height: 30px;"
                         "border: none;"
                         "font-size: 20px;"
                         "padding: 0 5px;"
                         "}"
                         "QListView {"
                         "outline: 0px;"
                         "}";

    // 将快速设置三个下拉列表中的所有项的前景色设置为黑色
    for (int l = 0; l < ui->sample->count(); l++) {
        ui->sample->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    }
    for (int l = 0; l < ui->target->count(); l++) {
        ui->target->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    }
    for (int l = 0; l < ui->yingguangLine->count(); l++) {
        ui->yingguangLine->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    }

    ui->sample->setStyleSheet(comboBoxSS + "QComboBox QAbstractItemView::item:selected {"
                                           "color: #000;"
                                           "border: none;"
                                           "background: rgba(75, 154, 250, 0.2);"
                                           "}");
    ui->target->setStyleSheet(comboBoxSS + "QComboBox QAbstractItemView::item:selected {"
                                           "color: #000;"
                                           "border: none;"
                                           "background: rgba(75, 154, 250, 0.2);"
                                           "}");
    ui->yingguangLine->setStyleSheet(comboBoxSS + "QComboBox QAbstractItemView::item:selected {"
                                                  "color: #000;"
                                                  "border: none;"
                                                  "background: rgba(75, 154, 250, 0.2);"
                                                  "}");

    // 获取被选中的孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 遍历被选中的孔位
    QList<QString> sampleNameList;
    foreach(QModelIndex index, indexList) {
        int row = index.row();
        int column = index.column();
        int count = 8 * column + row;
        if (reactionPlate.sampleList[count].name != "null") sampleNameList << reactionPlate.sampleList[count].name;
        // 更新孔位的选中状态
        for (int m = 0; m < ui->sampleList->rowCount(); m++) {
            QTableWidgetItem *check = ui->sampleList->item(m, 0);
            //如果反应板中的样本名字和样本列表中的名字相同
            if (reactionPlate.sampleList[count].name == ui->sampleList->item(m, 2)->text()) {
                // 设置样本列表中的样本为选中状态
                check->setCheckState(Qt::Checked);
            } else {
                // 设置样本列表中的样本为未选中状态
                check->setCheckState(Qt::Unchecked);
            }
        }

        // 更新靶基因列表的选中状态
        for (int m = 0; m < ui->targetList->rowCount(); m++) {
            QTableWidgetItem *check = ui->targetList->item(m, 0);
            check->setCheckState(Qt::Unchecked);
            for (int l = 0; l < 20; l++) {
                // 如果反应板中的靶基因名字和靶基因列表中的靶基因名字相同
                if (reactionPlate.targetList[count][l].name != "null") {
                    if (reactionPlate.targetList[count][l].name == ui->targetList->item(m, 2)->text()) {
                        // 设置靶基因列表中的靶基因为选中状态
                        check->setCheckState(Qt::Checked);
                    }
                }
            }
        }

        // 更新样本和靶基因参比荧光下拉框为为红色
        for (int l = 0; l < ui->sample->count(); l++) {
            if (reactionPlate.sampleList[count].name == ui->sample->itemText(l)) {
                ui->sample->setItemData(l, QColor(Qt::red), Qt::ForegroundRole);
                ui->sample->setStyleSheet(comboBoxSS + "QComboBox QAbstractItemView::item:selected {"
                                                       "color: red;"
                                                       "border: none;"
                                                       "background: rgba(75, 154, 250, 0.2);"
                                                       "}");
                break;
            }
        }

        for (int l = 0; l < ui->target->count(); l++) {
            for (int m = 0; m < 20; m++) {
                if (reactionPlate.targetList[count][m].name == ui->target->itemText(l)) {
                    ui->target->setItemData(l, QColor(Qt::red), Qt::ForegroundRole);
                    ui->target->setStyleSheet(comboBoxSS + "QComboBox QAbstractItemView::item:selected {"
                                                           "color: red;"
                                                           "border: none;"
                                                           "background: rgba(75, 154, 250, 0.2);"
                                                           "}");
                    break;
                }
            }
        }
        for (int l = 0; l < ui->yingguangLine->count(); l++) {
            for (int m = 0; m < 20; m++) {
                if (reactionPlate.targetList[count][m].reporter == ui->yingguangLine->itemText(l)) {
                    ui->yingguangLine->setItemData(l, QColor(Qt::red), Qt::ForegroundRole);
                    ui->yingguangLine->setStyleSheet(comboBoxSS + "QComboBox QAbstractItemView::item:selected {"
                                                                  "color: red;"
                                                                  "border: none;"
                                                                  "background: rgba(75, 154, 250, 0.2);"
                                                                  "}");
                    break;
                }
            }
        }
    }

    // 快速设置显示当前选中的样本
    if (!sampleNameList.empty()) {
        ui->sample->setCurrentText(sampleNameList.last());
    } else {
        ui->sample->setCurrentText("");
    }

    // 更新反应板的样本和靶基因信息
    markTable();

    // 阻塞复制品信号
    ui->copyCount->blockSignals(true);
    ui->startCount->blockSignals(true);

    // 设置复制品数量和起始编号
    ui->copyCount->setValue(1);
    ui->startCount->setValue(1);

    // 解除复制品信号阻塞
    ui->copyCount->blockSignals(false);
    ui->startCount->blockSignals(false);
}

/* 快速设置样本  in 是行索引的访问*/
void ExperimentPlateUi::samplebox(const int in) {
    if (in >= ui->sampleList->rowCount()) { // 输入样本回车添加超出索引
    } else {
        // 获取被选中的孔位
        QItemSelectionModel *selection = ui->sampleTable->selectionModel();
        QModelIndexList indexList = selection->selectedIndexes();
        // 遍历被选中的孔位
        foreach(QModelIndex index, indexList) {
            // 设置布局
            widgetLabel = createLabelWidget();

            // 计算选中的孔位编号
            int row = index.row();
            int column = index.column();
            int count = 8 * column + row;
            //  如果样本列表被选中的样本为空
            if (ui->sampleList->item(in, 2) == nullptr || ui->sampleList->item(in, 2)->text().isEmpty()) {
                // 设置反应板中的样本列表名字为空
                reactionPlate.sampleList[count].name = "null";
            } else {
                // 设置反应板中的样本列表名字为被选中的样本名字
                reactionPlate.sampleList[count].name = ui->sampleList->item(in, 2)->text();
            }

            // 如果样本列表被选中的样本注释为空
            if (ui->sampleList->item(in, 3) == nullptr || ui->sampleList->item(in, 3)->text().isEmpty()) {
                // 设置反应板中的样本列表注释为空
                reactionPlate.sampleList[count].remarks = "null";
            } else {
                // 设置反应板中的样本列表注释为被选中的样本注释
                reactionPlate.sampleList[count].remarks = ui->sampleList->item(in, 3)->text();
            }
            // 设置反应板中的样本列表颜色为被选中的样本颜色
            QColor col = ui->sampleList->item(in, 1)->backgroundColor();
            reactionPlate.sampleList[count].color_value = colorTostring(col);

            // 下面三个if控制反应板查看按钮的两个样本选项勾选情况
            // 反应板查看按钮的第一个选项是否是"样本名称"，以及第一个样本名称和第三个选项样本颜色是否被勾选
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                QString name = reactionPlate.sampleList[count].name; // 获取当前位置的样本名称
                copySampleName[count] = ""; // 清空copySampleName
                if (name != "null") {  // 如果样本名称不为空
                    QLabel *label = createLabel(name);
                    // 获取当前位置的样本颜色，并转换为QColor对象
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
                    vLayout->addWidget(label);
                }
            }
            // 反应板查看按钮的第一个选项是否是"样本名称"，第一个样本名称被勾选 并且 第三个选项样本颜色没有被勾选
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
                // 获取反应板的样本列表中第count个样本的名称
                QString name = reactionPlate.sampleList[count].name;
                // 清空copySampleName
                copySampleName[count] = "";
                // 如果样本名称不是"null"
                if (name != "null") {
                    // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                    QLabel *label = createLabel(name);
                    // 将标签添加到垂直布局中
                    vLayout->addWidget(label);
                }
            }
            // 反应板查看按钮的第一个选项是否是"样本名称"，第一个样本名称未被勾选 并且 第三个选项样本颜色被勾选
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                // 获取反应板的样本列表中第count个样本的名称
                QString name = reactionPlate.sampleList[count].name;
                // 清空copySampleName
                copySampleName[count] = "";
                // 如果样本名称不是"null"
                if (name != "null") {
                    // 创建一个标签对象
                    QLabel *label = new QLabel();
                    // 获取反应板的样本列表中第count个样本的颜色值，并转换为QColor对象
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    // 将标签添加到垂直布局中
                    vLayout->addWidget(label);
                }
            }

            int p = 0; // 控制反应板布局
            for (int l = 0; l < 20; l++) {
                // 如果表格过滤器的第二个菜单项的提示是"靶基因"，并且它被选中了
                if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                        ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
                    // 如果反应板的列表中第count个样本的第l个靶基因的报告基因不是"null"
                    if (reactionPlate.targetList[count][l].reporter != "null") {
                        createTargetLabel(reactionPlate, count, l, p, false);
                    }
                }
            }

            // 设置反应板布局
            gLayout->setMargin(0);
            gLayout->setSpacing(0);
            vLayout->addLayout(gLayout);
            // 设置反应板孔位
            ui->sampleTable->setCellWidget(row, column, widgetLabel);

        }

        // 更新和渲染视图
        markTable();
        renderDetailTable();
        //      updateTable();
    }

    // 设置样本名为空白
    ui->sample->setCurrentIndex(-1);
}

/* 快速设置靶基因 in 是行索引的访问 */
void ExperimentPlateUi::targetbox(const int in) {
    // 获取被选中的孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    int a = 0;
    // 遍历被选中的孔位
    foreach(QModelIndex index, indexList) {
        // 设置布局
        widgetLabel = createLabelWidget();
        // 获取反应板孔位的行号和列号， 并计算
        int row = index.row();
        int column = index.column();
        int count = 8 * column + row;
        int f = 0;
        int t;
        int h = 0;
        // 遍历靶基因
        for (int l = 0; l < 20; l++) {
            // 如果反应板的列表中第count个样本的第l个靶基因的报告基因不是"null"
            if (reactionPlate.targetList[count][l].reporter != "null") {
                // 获取反应板的列表中第count个样本的第l个靶基因的报告基因文本
                QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, in, 3);
                QString string_reporter = combo_reporter->currentText();
                // 如果反应板的列表中第count个样本的第l个靶基因的报告基因 和 靶基因的列表中第in列相同
                if (reactionPlate.targetList[count][l].name == ui->target->itemText(in)) {
                    if (a == 0) {
                        cusMsg->show(this, CMsg::CWarning, "提示", "该报告基因已经添加");
                        a++;
                    }
                    f = 1;
                    break;
                }
                if (reactionPlate.targetList[count][l].reporter == string_reporter) {
                    if (a == 0) {
                        cusMsg->show(this, CMsg::CWarning, "提示", "该报告基因已经添加");
                        a++;
                    }
                    f = 1;
                    break;
                }
            } else {
                if (h > 0) { continue; }
                h++;
                t = l;
            }
        }
        if (f == 0) {
            // 设置反应板靶基因信息
            if (ui->targetList->item(in, 2) == nullptr || ui->targetList->item(in, 2)->text().isEmpty()) {
                reactionPlate.targetList[count][t].name = "null";
            } else {
                reactionPlate.targetList[count][t].name = ui->targetList->item(in, 2)->text();
            }
            QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, in, 3);
            QString string_reporter = combo_reporter->currentText();
            reactionPlate.targetList[count][t].reporter = string_reporter;
            QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, in, 4);
            QString string_quencher = combo_quencher->currentText();
            reactionPlate.targetList[count][t].quencher = string_quencher;

            QComboBox *combo_type = getComboBoxFromTable(ui->targetList, in, 5);
            QString string_type = combo_type->currentText();
            reactionPlate.targetList[count][t].type = string_type;
            if (ui->targetList->item(in, 6) == nullptr || ui->targetList->item(in, 6)->text().isEmpty()) {
                reactionPlate.targetList[count][t].quantity = "null";
            } else {
                reactionPlate.targetList[count][t].quantity = ui->targetList->item(in, 6)->text();
            }
            if (ui->targetList->item(in, 7) == nullptr || ui->targetList->item(in, 7)->text().isEmpty()) {
                reactionPlate.targetList[count][t].explain = "null";
            } else {
                reactionPlate.targetList[count][t].explain = ui->targetList->item(in, 7)->text();
            }
            QColor col = ui->targetList->item(in, 1)->backgroundColor();
            reactionPlate.targetList[count][t].color = colorTostring(col);
        }
        // 反应板信息过滤
        if (reactionPlate.sampleList[count].name != "null") {
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                QString name = reactionPlate.sampleList[count].name;
                if (copySampleName[count] != "") {
                    name = copySampleName[count];
                }
                QLabel *label = createLabel(name);
                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                vLayout->addWidget(label);
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
                QString name = reactionPlate.sampleList[count].name;
                if (name != "null") {
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                    QLabel *label = createLabel(name);
                    // 将标签添加到垂直布局中
                    vLayout->addWidget(label);
                }
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                QString name = reactionPlate.sampleList[count].name;
                if (name != "null") {
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    QLabel *label = new QLabel();
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    vLayout->addWidget(label);
                }
            }
        }
        int p = 0;
        for (int l = 0; l < 20; l++) {
            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                    ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
                if (reactionPlate.targetList[count][l].reporter != "null") {
                    createTargetLabel(reactionPlate, count, l, p, false);
                }
            }
        }
        // 设置布局
        gLayout->setMargin(0);
        gLayout->setSpacing(0);
        vLayout->addLayout(gLayout);
        ui->sampleTable->setCellWidget(row, column, widgetLabel);
    }
    // 更新渲染视图
    markTable();
    renderDetailTable();
    updateTable();
    ui->target->setCurrentIndex(-1);
}

/* 高级设置根据样本类型设置数量可编辑 */
void ExperimentPlateUi::targetQuantity() {
    // 获取用户选择的靶基因列表
    QItemSelectionModel *selection = ui->targetList->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 遍历用户选择的靶基因列表
    foreach(QModelIndex index, indexList) {
        // 如果用户选择的是靶基因数量列
        if (index.column() == 6) {
            // 获取靶基因类型和数量
            QComboBox *combo_type = getComboBoxFromTable(ui->targetList, index.row(), 5);
            QString string_type = combo_type->currentText();
            QTableWidgetItem *item = ui->targetList->item(index.row(), 6);
            // 如果靶基因类型为标准，则数量可编辑
            if (string_type.contains("and")) {
                //                item->setText("1.0");
                item->setFlags(item->flags() | Qt::ItemIsEditable);
            } else {
                //                item->setText("");
                item->setFlags(item->flags() & ~Qt::ItemIsEditable);
            }
        }
    }
}

/* 删除选中孔位信息 */
void ExperimentPlateUi::clearTable() {
    // 获取被选中的孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 遍历被选中的孔位
    foreach(QModelIndex index, indexList) {
        // 获取反应板孔位的行号和列号
        int row = index.row();
        int column = index.column();
        // 计算反应板对应孔位的位置编号
        int count = 8 * column + row;
        // 删除孔位信息
        ui->sampleTable->removeCellWidget(row, column);
        for (int l = 0; l < 20; l++) {
            reactionPlate.targetList[count][l].name = "null";
            reactionPlate.targetList[count][l].reporter = "null";
            reactionPlate.targetList[count][l].quencher = "null";
            reactionPlate.targetList[count][l].type = "null";
            reactionPlate.targetList[count][l].quantity = "null";
            reactionPlate.targetList[count][l].color = "null";
            reactionPlate.targetList[count][l].explain = "null";
        }
        reactionPlate.sampleList[count].name = "null";
        reactionPlate.sampleList[count].remarks = "null";
        reactionPlate.sampleList[count].color_value = "null";
        copySampleName[count] = "";
    }
    // 更新反应板信息
    markTable();
}

/* 样板表过滤功能 */
void ExperimentPlateUi::filter(QAction *action) {
    // 遍历所有孔位
    for (int l = 0; l < 96; l++) {
        // 设置布局
        widgetLabel = createLabelWidget();
        // 如果选择了样本颜色和样本名称
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                reactionPlate.sampleList[l].name != "null" &&
                ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
            // 复制功能
            QString name = reactionPlate.sampleList[l].name;
            if (copySampleName[l] != "") {
                name = copySampleName[l];
            }
            QLabel *label = createLabel(name);
            QColor color = stringToColor(reactionPlate.sampleList[l].color_value);
            QString mRgbStr = QString::number(color.rgb(), 16);
            widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
            vLayout->addWidget(label);
        }
        // 如果选择了样本名称没有选择样本颜色
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
            QString name = reactionPlate.sampleList[l].name;
            // 复制功能
            if (name != "null") {
                if (copySampleName[l] != "") {
                    name = copySampleName[l];
                }
                // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                QLabel *label = createLabel(name);
                // 将标签添加到垂直布局中
                vLayout->addWidget(label);
            }
        }
        // 如果选中了样本颜色没有选择样本名称
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
            QString name = reactionPlate.sampleList[l].name;
            // 复制功能
            if (name != "null") {
                if (copySampleName[l] != "") {
                    name = copySampleName[l];
                }
                // 设置反应板样式
                QLabel *label = new QLabel();
                QColor color = stringToColor(reactionPlate.sampleList[l].color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                vLayout->addWidget(label);
            }
        }

        int p = 0; // 控制反应板布局
        // 如果选择了靶基因
        if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
            // 遍历通道
            for (int m = 0; m < 20; m++) {
                // 如果通道不为空
                if (reactionPlate.targetList[l][m].reporter != "null") {
                    createTargetLabel(reactionPlate, l, m, p, false);
                }
            }
        }
        // 设置反应板布局
        int row = l % 8;
        int column = l / 8;
        gLayout->setMargin(0);
        gLayout->setSpacing(0);
        vLayout->addLayout(gLayout);
        ui->sampleTable->setCellWidget(row, column, widgetLabel);
    }
    // 更新渲染视图
    renderDetailTable();
}

/* 右键显示菜单功能 */
void ExperimentPlateUi::slot_DL_RcOnTw(QPoint pos) {
    tableMenu->exec(QCursor::pos());
}

/* 双击反应板功能 */
void ExperimentPlateUi::doubleClickedTable(int row, int column) {
    // 清空双击设置反应板的 靶基因,样本点和样本类型
    view->ui->sampleComboBox->clear();
    view->ui->sampleComboBox->setFixedSize(208, 32);
    view->ui->targetComboBox->clear();
    view->ui->targetComboBox->setFixedSize(208, 32);
    view->ui->typeComboBox->clear();
    view->ui->typeComboBox->setFixedSize(208, 32);
    view->ui->countLineEdit->setFixedSize(208, 32);


    // 添加双击设置反应板的 靶基因,样本点和样本类型
    for (int m = 0; m < ui->sampleList->rowCount(); m++) {
        view->ui->sampleComboBox->addItem(ui->sampleList->item(m, 2)->text());
    }
    for (int m = 0; m < ui->targetList->rowCount(); m++) {
        view->ui->targetComboBox->addItem(ui->targetList->item(m, 2)->text());
    }
    for (int m = 0; m < targetTypeFromConfig.length(); m++) {
        view->ui->typeComboBox->addItem(targetTypeFromConfig[m]);
    }

    // 设置双击反应板的信息
    for (int l = 0; l < ui->targetList->rowCount(); l++) {
        if (view->ui->targetComboBox->currentText() == targetListInfo[l][1]) {
            view->ui->typeComboBox->setCurrentText(targetListInfo[l][4]);
            view->ui->countLineEdit->setText(targetListInfo[l][5]);
        }
    }

    // 遍历孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    foreach(QModelIndex index, indexList) {
        // 计算孔位编号
        int row = index.row();
        int column = index.column();
        int count = column * 8 + row;
        QString name = reactionPlate.sampleList[count].name;

        if (name != "null") {
            // 设置样本名称
            view->ui->sampleComboBox->setCurrentText(name);
            // 设置样本颜色
        }
        QString target = reactionPlate.targetList[count][0].name;
        if (target != "null") {
            // 设置靶基因
            view->ui->targetComboBox->setCurrentText(target);
        }
        QString type = reactionPlate.targetList[count][0].type;
        if (type != "null") {
            // 设置样本类型
            view->ui->typeComboBox->setCurrentText(type);
        }
        // 如果样本类型设置为标准
        if (view->ui->typeComboBox->currentText().contains("and")) {
            // 允许设置样本数量
            view->ui->countLineEdit->setEnabled(true);
            // 遍历通道
            for (int i = 0; i < 20; i++) {
                // 如果反应板靶基因名称与双击出来的设置框靶基因名称相同
                if (reactionPlate.targetList[count][i].name == view->ui->targetComboBox->currentText()) {
                    // 如果存在设置好的数量，直接显示出来
                    if (reactionPlate.targetList[count][i].quantity != "null" &&
                            reactionPlate.targetList[count][i].quantity != "") {
                        view->ui->countLineEdit->setText(reactionPlate.targetList[count][i].quantity);
                    } else {
                        // 否则设置默认值1.0
                        view->ui->countLineEdit->setText("1.0");
                    }
                }
            }
        } else {
            // 如果样本类型不是标准，不允许设置样本数量
            view->ui->countLineEdit->setEnabled(false);
            view->ui->countLineEdit->setText("");
        }
    }

    // 设置弹窗出现位置
//    QPoint moveTo = this->parentWidget()->mapToGlobal(QPoint(0, -95));
//    moveTo -= QPoint(500, -50);
//    view->move(moveTo);

    // 显示弹窗
    view->show();
}

/* 反应板双击弹窗设置样本 in (行索引的访问) */
void ExperimentPlateUi::sampleSettingBox(const int in) {
    LOG << "反应板双击弹窗设置样本";
    // 获取反应板孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 遍历孔位
    foreach(QModelIndex index, indexList) {
        // 设置反应板孔位布局
        widgetLabel = createLabelWidget();
        // 获取并计算孔位编号
        int row = index.row();
        int column = index.column();
        int count = 8 * column + row;
        if (ui->sampleList->item(in, 2) == nullptr || ui->sampleList->item(in, 2)->text().isEmpty()) {
            reactionPlate.sampleList[count].name = "null";
        } else {
            reactionPlate.sampleList[count].name = ui->sampleList->item(in, 2)->text();
        }
        if (ui->sampleList->item(in, 3) == nullptr || ui->sampleList->item(in, 3)->text().isEmpty()) {
            reactionPlate.sampleList[count].remarks = "null";
        } else {
            reactionPlate.sampleList[count].remarks = ui->sampleList->item(in, 3)->text();
        }
        QColor col = ui->sampleList->item(in, 1)->backgroundColor();
        reactionPlate.sampleList[count].color_value = colorTostring(col);

        // 反应板信息过滤
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
            QString name = reactionPlate.sampleList[count].name;
            copySampleName[count] = "";
            QLabel *label = createLabel(name);
            QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
            QString mRgbStr = QString::number(color.rgb(), 16);
            widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
            vLayout->addWidget(label);
        }
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
            QString name = reactionPlate.sampleList[count].name;
            copySampleName[count] = "";
            if (name != "null") {
                // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                QLabel *label = createLabel(name);
                // 将标签添加到垂直布局中
                vLayout->addWidget(label);
            }
        }
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
            QString name = reactionPlate.sampleList[count].name;
            copySampleName[count] = "";
            if (name != "null") {
                QLabel *label = new QLabel();
                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                vLayout->addWidget(label);
            }
        }

        int p = 0;
        // 设置反应板靶基因信息
        for (int l = 0; l < 20; l++) {
            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                    ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
                if (reactionPlate.targetList[count][l].reporter != "null") {
                    LOG << "----------------------------------";
                    createTargetLabel(reactionPlate, count, l, p, false);
                }
            }
        }
        // 设置布局
        gLayout->setMargin(0);
        gLayout->setSpacing(0);
        vLayout->addLayout(gLayout);
        ui->sampleTable->setCellWidget(row, column, widgetLabel);
    }

    // 渲染和更新孔位信息表
    markTable();
    renderDetailTable();
}


/* 反应板双击弹窗设置靶基因 in(行索引的访问) */
void ExperimentPlateUi::targetSettingBox(const int in) {
    // 获取被选中的孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    int a = 0;
    // 遍历孔位
    foreach(QModelIndex index, indexList) {
        // 设置布局
        widgetLabel = createLabelWidget();
        // 获取反应板孔位的行号和列号， 并计算反应板对应孔位的位置编号
        int row = index.row();
        int column = index.column();
        int count = 8 * column + row;

        int f = 0;
        int t;
        int h = 0;
        // 检测是否已经添加了该靶基因
        for (int l = 0; l < 20; l++) {
            if (reactionPlate.targetList[count][l].reporter != "null") {
                QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, in, 3);
                QString string_reporter = combo_reporter->currentText();
                if (reactionPlate.targetList[count][l].name == view->ui->targetComboBox->itemText(in)) {
                    if (a == 0) {
                        //                      LOG << "surprise";
                        cusMsg->show(this, CMsg::CWarning, "提示", "该报告基因已经添加");
                        //                      LOG << "after surprise";
                        a++;
                    }
                    f = 1;
                    break;
                }
                if (reactionPlate.targetList[count][l].reporter == string_reporter) {
                    if (a == 0) {
                        //                      LOG << "surprise";
                        cusMsg->show(this, CMsg::CWarning, "提示", "该报告基因已经添加");
                        //                      LOG << "after surprise";
                        a++;
                    }
                    f = 1;
                    break;
                }
            } else {
                if (h > 0) { continue; }
                h++;
                t = l;
            }
        }
        if (f == 0) {
            // 设置反应板靶基因信息
            if (ui->targetList->item(in, 2) == nullptr || ui->targetList->item(in, 2)->text().isEmpty()) {
                reactionPlate.targetList[count][t].name = "null";
            } else {
                reactionPlate.targetList[count][t].name = ui->targetList->item(in, 2)->text();
            }

            QString string_reporter = getComboBoxFromTable(ui->targetList, in, 3)->currentText();
            reactionPlate.targetList[count][t].reporter = string_reporter;

            QString string_quencher = getComboBoxFromTable(ui->targetList, in, 4)->currentText();
            reactionPlate.targetList[count][t].quencher = string_quencher;
            // 修改下面代码从reactionPlate获取数据
            //                QString string_type = getComboBoxFromTable(ui->targetList, in, 5)->currentText();
            //                reactionPlate.targetList[count][t].type = string_type;
            QString &string_type = reactionPlate.targetList[count][t].type;
            if (string_type == "null") {
                reactionPlate.targetList[count][t].type = "unknown(未知)";
            }
            LOG << "string_type: " << string_type;

            // 设置数量
            QString &string_quantity = reactionPlate.targetList[count][t].quantity;
            if (string_type == "stander(标准)") {
                string_quantity = string_quantity == "null" ? "1.0" : string_quantity;
            } else {
                string_quantity = "null";
            }
            //                if (ui->targetList->item(in, 6) == nullptr || ui->targetList->item(in, 6)->text().isEmpty()) {
            //                    reactionPlate.targetList[count][t].quantity = "null";
            //                } else {
            //                    reactionPlate.targetList[count][t].quantity = ui->targetList->item(in, 6)->text();
            //                }


            if (ui->targetList->item(in, 7) == nullptr || ui->targetList->item(in, 7)->text().isEmpty()) {
                reactionPlate.targetList[count][t].explain = "null";
            } else {
                reactionPlate.targetList[count][t].explain = ui->targetList->item(in, 7)->text();
            }
            QColor col = ui->targetList->item(in, 1)->backgroundColor();
            reactionPlate.targetList[count][t].color = colorTostring(col);
        }
        // 反应板信息过滤
        if (reactionPlate.sampleList[count].name != "null") {
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                QString name = reactionPlate.sampleList[count].name;
                if (copySampleName[count] != "") {
                    name = copySampleName[count];
                }
                QLabel *label = createLabel(name);
                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                vLayout->addWidget(label);
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
                QString name = reactionPlate.sampleList[count].name;
                if (name != "null") {
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                    QLabel *label = createLabel(name);
                    // 将标签添加到垂直布局中
                    vLayout->addWidget(label);
                }
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                QString name = reactionPlate.sampleList[count].name;
                if (name != "null") {
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    QLabel *label = new QLabel();
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    vLayout->addWidget(label);
                }
            }
        }

        int p = 0;
        for (int l = 0; l < 20; l++) {
            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                    ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
                if (reactionPlate.targetList[count][l].reporter != "null") {
                    createTargetLabel(reactionPlate, count, l, p, false);
                }
            }
        }
        // 设置布局
        gLayout->setMargin(0);
        gLayout->setSpacing(0);
        vLayout->addLayout(gLayout);
        ui->sampleTable->setCellWidget(row, column, widgetLabel);
    }

    // 设置右键菜单的文本信息
    for (int l = 0; l < ui->targetList->rowCount(); l++) {
        if (view->ui->targetComboBox->currentText() == targetListInfo[l][1]) {
            view->ui->typeComboBox->setCurrentText(targetListInfo[l][4]);
            view->ui->countLineEdit->setText(targetListInfo[l][5]);
        }
    }

    // 更新和渲染视图
    renderDetailTable();
    markTable();
}

/* 选择耗材类型 */
void ExperimentPlateUi::materialType(const int index) {
    // 查看孔位信息图时隐藏反应板
    if ((ui->materialTable->isHidden() == false && ui->matetialTable_1->isHidden() == true) ||
            (ui->materialTable->isHidden() == true && ui->matetialTable_1->isHidden() == false)) {
        ui->sampleTable->hide();
    }

    // 清空反应板信息
    clearPlateInformation();

    /* 获取当前所选耗材类型 */
    QString conume = ui->materialType->currentText();

    /* 显示和隐藏相关控件 */
    if (conume == "芯片-16" && ui->sampleTable->isHidden() == true && ui->detailTable->isHidden() == true) {
        ui->materialTable->show();
        ui->matetialTable_1->hide();
    }
    if (conume == "管式" && ui->sampleTable->isHidden() == true && ui->detailTable->isHidden() == true) {
        ui->materialTable->hide();
        ui->matetialTable_1->show();
    }

    /* 根据耗材类型设置表格行列数 */
    readAndRenderTableRowColumnFromXML(conume);
    startMaterial();

    int in = ui->materialType->currentIndex();
    int allIndex = 0;
    if (in == 0) {
        allIndex = 16;
        ui->copyCount->setRange(1, 16);
        ui->startCount->setRange(1, 16);
    } else if (in == 1) {
        allIndex = 32;
        ui->copyCount->setRange(1, 32);
        ui->startCount->setRange(1, 32);
    }

    ui->copyCount->setValue(1);
    ui->startCount->setValue(1);
    ui->sampleTable->setCurrentCell(0, 0);

    /* 初始化孔位标识信息 */
    ui->sampleInfoLabel->setText(
                "U:" + QString::number(0) + " S:" + QString::number(0) + " N:" + QString::number(0) + "    空闲孔位: " +
                QString::number(allIndex));
}

/* 打开wlk渲染反应板 */
bool ExperimentPlateUi::renderSample() {
    renderSamplePlate = reactionPlate;

    // 储存报告基因和淬灭基因
    QList<QString> reporterBox;
    QList<QString> quencherBox;

    QList<QString> reporterlist;
    QList<QString> quencherlist;

    // l: QHash<QString, QString> & 遍历染料库配置
    for (auto &l: dyeFromConfig) {
        if (l["type"] == "报告基因") {
            reporterBox.append(l["name"]);
            reporterlist.append(l["name"]);
        } else if (l["type"] == "淬火基因") {
            quencherBox.append(l["name"]);
            quencherlist.append(l["name"]);
        }
    }
    // 根据从配置文件中读取的耗材类型渲染表格
    LOG << 2;
    if(!readAndRenderTableRowColumnFromXML(renderSamplePlate.consumables)) return false;

    // 设置耗材类型
    if (renderSamplePlate.consumables == "管式") {
        ui->materialType->setCurrentIndex(1);
    }
    // 遍历孔位
    for (int i = 0; i < 96; i++) {
        // 反应板是否含有样本标识
        int sflag = 0;
        // 如果反应板样本名不为空
        if (renderSamplePlate.sampleList[i].name != "null") {
            // 遍历样本列表
            for (int l = 0; l < ui->sampleList->rowCount(); l++) {
                // 如果反应板样本名和样本列表样本名相同
                if (renderSamplePlate.sampleList[i].name == ui->sampleList->item(l, 2)->text()) {
                    sflag = 1;
                    break;
                }
            }
            // 没有样本
            if (sflag == 0) {
                // 样本行数
                int samplerow = ui->sampleList->rowCount();

                // 样本行数 + 1
                ui->sampleList->setRowCount(samplerow + 1);

                // 新建样本并设置未勾选
                QTableWidgetItem *check = new QTableWidgetItem();
                check->setCheckState(Qt::Unchecked);

                // 设置样本颜色 样本名 样本注释
                QString strname = renderSamplePlate.sampleList[i].name;
                QTableWidgetItem *name = new QTableWidgetItem(strname);
                QColor qc = selectColor(flag[3], 1);
                QString strcolor;
                QTableWidgetItem *color = new QTableWidgetItem(strcolor);
                color->setBackgroundColor(qc);

                QString strexplain = renderSamplePlate.sampleList[i].remarks;
                QTableWidgetItem *explain = new QTableWidgetItem(strexplain);

                // 设置样本信息
                ui->sampleList->setItem(flag[3], 0, check);
                ui->sampleList->setItem(flag[3], 1, color);
                ui->sampleList->setItem(flag[3], 2, name);
                ui->sampleList->setItem(flag[3], 3, explain);

                // 设置样本颜色不可编辑和选择
                QTableWidgetItem *item = ui->sampleList->item(flag[3], 1);
                item->setFlags(item->flags() & (~Qt::ItemIsEditable));
                item->setFlags(item->flags() & (~Qt::ItemIsSelectable));

                flag[3]++;
                flag[5]++;
            }
        }


        // 遍历通道
        for (int m = 0; m < 20; m++) {
            // 反应板是否含有靶基因标识
            int tflag = 0;
            // 如果反应板靶基因名不为空
            if (renderSamplePlate.targetList[i][m].name != "null") {
                // 遍历靶基因列表
                for (int l = 0; l < ui->targetList->rowCount(); l++) {
                    // 如果反应板靶基因名和靶基因列表靶基因名相同
                    if (renderSamplePlate.targetList[i][m].name == ui->targetList->item(l, 2)->text()) {
                        // 靶基因标识置1
                        tflag = 1;

                        // 设置靶基因颜色
                        QString strcolor;
                        QColor qc = stringToColor(renderSamplePlate.targetList[i][m].color);
                        QTableWidgetItem *color = ui->targetList->item(l, 1);
                        color->setBackgroundColor(qc);

                        // --------
                        // 设置靶基因报告基因
                        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
                        combo_reporter->setCurrentText(renderSamplePlate.targetList[i][m].reporter);
                        int key = 0;
                        // 遍历报告基因
                        for (int k = 0; k < combo_reporter->count(); k++) {
                            // 如果反应板报告基因和靶基因列表报告基因相同
                            if (renderSamplePlate.targetList[i][m].reporter == combo_reporter->itemText(k)) {
                                key = 1; // key 置 1
                            }
                        }
                        // 不存在此报告基因, 添加此报告基因
                        if (key == 0) {
                            combo_reporter->addItem(renderSamplePlate.targetList[i][m].reporter);
                        }
                        combo_reporter->setCurrentText(renderSamplePlate.targetList[i][m].reporter);

                        // 设置靶基因淬火基因
                        QComboBox *combo_type = getComboBoxFromTable(ui->targetList, l, 5);
                        combo_type->setCurrentText(renderSamplePlate.targetList[i][m].type);
                        break;
                    }
                }
                // 不存在此靶基因, 添加此靶基因
                if (tflag == 0) {
                    int targetrow = ui->targetList->rowCount();
                    ui->targetList->setRowCount(targetrow + 1);

                    QTableWidgetItem *check = new QTableWidgetItem();
                    check->setCheckState(Qt::Unchecked);

                    QString strname = renderSamplePlate.targetList[i][m].name;
                    QTableWidgetItem *name = new QTableWidgetItem(strname);

                    targetName.append(strname);

                    QComboBox *reporter = new QComboBox();
                    reporter->setStyleSheet(style);
                    int key = 0;
                    for (int k = 0; k < reporterBox.length(); k++) {
                        if (renderSamplePlate.targetList[i][m].reporter == reporterBox[k]) {
                            key = 1;
                        }
                        reporter->addItem(reporterBox[k]);
                    }
                    if (key == 0) {
                        reporter->addItem(renderSamplePlate.targetList[i][m].reporter);
                    }
                    reporter->setCurrentText(renderSamplePlate.targetList[i][m].reporter);


                    QComboBox *quencher = new QComboBox();
                    quencher->setStyleSheet(style);

                    int key2 = 0;
                    for (int k = 0; k < quencherBox.length(); k++) {
                        if (renderSamplePlate.targetList[i][m].quencher == quencherBox[k]) {
                            key2 = 1;
                        }
                        quencher->addItem(quencherBox[k]);
                    }
                    if (key2 == 0) {
                        quencher->addItem(renderSamplePlate.targetList[i][m].quencher);
                    }
                    quencher->setCurrentText(renderSamplePlate.targetList[i][m].quencher);


                    QString strexplain;
                    QTableWidgetItem *explain = new QTableWidgetItem(strexplain);

                    QComboBox *type = new QComboBox();
                    type->setStyleSheet(style);
                    for (int k = 0; k < targetTypeFromConfig.length(); k++) {
                        type->addItem(targetTypeFromConfig[k]);
                    }

                    type->setCurrentText(renderSamplePlate.targetList[i][m].type);


                    QString strcolor;
                    QColor qc = stringToColor(renderSamplePlate.targetList[i][m].color);
                    QTableWidgetItem *color = new QTableWidgetItem(strcolor);
                    color->setBackgroundColor(qc);

                    QTableWidgetItem *quantity = new QTableWidgetItem();
                    quantity->setFlags(quantity->flags() & 33);

                    ui->targetList->setItem(flag[2], 0, check);
                    ui->targetList->setItem(flag[2], 1, color);
                    ui->targetList->setItem(flag[2], 2, name);
                    ui->targetList->setCellWidget(flag[2], 3, reporter);
                    ui->targetList->setCellWidget(flag[2], 4, quencher);
                    ui->targetList->setCellWidget(flag[2], 5, type);
                    ui->targetList->setItem(flag[2], 6, quantity);
                    ui->targetList->setItem(flag[2], 7, explain);
                    QTableWidgetItem *item = ui->targetList->item(flag[2], 1);
                    item->setFlags(item->flags() & (~Qt::ItemIsEditable));
                    item->setFlags(item->flags() & (~Qt::ItemIsSelectable));

                    flag[2]++;
                    flag[4]++;
                }
            }
        }
    }

    // 渲染参比荧光
    ui->yingguangLine->setCurrentText(this->canBi);
    // 渲染备注
    ui->plateComment->setText(this->plateRemarks);

    // 更新和渲染视图
    reactionPlate = renderSamplePlate;
    updateTarget();
    updateSample();
    updateTable();
    markTable();
}

/* 反应板判断样本名称是否相同但是被舍弃掉的方法 */
//void ExperimentPlateUi::changeSampleName(QModelIndex index_1,QModelIndex index_2,QVector<int> in){
//    if(ui->sampleList->item(index_1.row(), 2) == nullptr || ui->sampleList->item(index_1.row(), 2)->text().isEmpty()){
//    }
//    else{
//        int flag= 0;
//        QString preName = sampleName[index_1.row()];
//        QString name = ui->sampleList->item(index_1.row(), 2)->text();
//        for(int i = 0; i < sampleName.length(); i ++){
//            if(i != index_1.row() && sampleName[i] == name){
//                QMessageBox::warning(this, "提示", "样本名重复~");
//                flag = 1;
//                break;
//            }
//        }
//        if(flag == 0){
//            sampleName[index_1.row()] = name;
//        }
//        ui->sampleList->item(index_1.row(), 2)->setText(sampleName[index_1.row()]);

//        for(int i = 0; i < 96; i ++){
//            if(reactionPlate.sampleList[i].name == preName){
//                reactionPlate.sampleList[i].name = sampleName[index_1.row()];
//            }
//        }

//        updateTable();
//    }

//}

/* 反应板判断靶基因名称是否相同的方法 */
void ExperimentPlateUi::changeTargetName(QModelIndex index_1, QModelIndex index_2, QVector<int> in) {
    if (ui->targetList->item(index_1.row(), 6) == nullptr) {
    } else {
        int flag = 0;
        //
        QString preName = targetName[index_1.row()];
        QString name = ui->targetList->item(index_1.row(), 2)->text();
        for (int i = 0; i < targetName.length(); i++) {
            if (i != index_1.row() && targetName[i] == name) {
                cusMsg->show(this, CMsg::CWarning, "提示", "靶基因名重复");
                flag = 1;
                break;
            }
        }
        if (flag == 0) {
            targetName[index_1.row()] = name;
        }
        ui->targetList->item(index_1.row(), 2)->setText(targetName[index_1.row()]);

        for (auto &i: reactionPlate.targetList) {
            for (int k = 0; k < 4; k++) {
                if (i[k].name == preName) {
                    i[k].name = targetName[index_1.row()];
                }
            }
        }


    }
}

/* 高级设置导入样本信息 */
void ExperimentPlateUi::importSample() {
    // 获取样本库中全部数据
    allSampleInfos = sampleLibrary->show();
    // 遍历样本库
    for (auto rows: allSampleInfos) {
        // 添加样本
        int samplerow = ui->sampleList->rowCount();
        ui->sampleList->setRowCount(samplerow + 1);

        QTableWidgetItem *check = new QTableWidgetItem();
        check->setCheckState(Qt::Unchecked);

        // 没用上
        QString strname;
        if (import_sample == 0) {
            strname = rows["name"];
        } else {
            strname = rows["name"] + "_" + QString::number(import_sample);
        }

        // 设置样本信息
        QTableWidgetItem *name = new QTableWidgetItem(strname);
        QColor qc = selectColor(flag[3], 1);
        QString strcolor;
        QTableWidgetItem *color = new QTableWidgetItem(strcolor);
        color->setBackgroundColor(qc);

        QString strremarks = rows["remarks"];
        QTableWidgetItem *remarks = new QTableWidgetItem(strremarks);

        ui->sampleList->setItem(flag[3], 0, check);
        ui->sampleList->setItem(flag[3], 1, color);
        ui->sampleList->setItem(flag[3], 2, name);
        ui->sampleList->setItem(flag[3], 3, remarks);

        QTableWidgetItem *item = ui->sampleList->item(flag[3], 1);
        item->setFlags(item->flags() & (~Qt::ItemIsEditable));
        item->setFlags(item->flags() & (~Qt::ItemIsSelectable));

        flag[3]++;
        flag[5]++;
    }
    // 更新渲染视图
    updateSample();
}

/* 高级设置靶基因导入功能 */
void ExperimentPlateUi::importTarget() {
    QList<QString> reporterName;
    QList<QString> quencherName;
    // 遍历靶基因列表
    for (int l = 0; l < ui->targetList->rowCount(); l++) {
        // 存储报告基因和淬火基因
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, l, 4);

        if (combo_reporter && combo_quencher) {
            reporterName.append(combo_reporter->currentText());
            quencherName.append(combo_quencher->currentText());
        }

    }
    // 设置报告基因和淬火基因下拉框
    QList<QString> reporterBox;
    QList<QString> quencherBox;

    for (int l = 0; l < dyeFromConfig.length(); l++) {
        if (dyeFromConfig[l]["type"] == "报告基因") {
            reporterBox.append(dyeFromConfig[l]["name"]);
        } else if (dyeFromConfig[l]["type"] == "淬火基因") {
            quencherBox.append(dyeFromConfig[l]["name"]);
        }
    }

    // 获取染料库中全部数据
    allDyeInfos = dyeLibrary->show();

    for (int l = 0; l < ui->targetList->rowCount(); l++) {
        // 设置下拉框
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, l, 4);

        // 遍历染料库
        for (auto dyeInfo: allDyeInfos) {
            if (dyeInfo["type"] == "二者皆是") {
                // 判断报告基因名字是否重复，不重复则添加
                int fl = 0;
                for (int m = 0; m < reporterBox.length(); m++) {
                    if (dyeInfo["name"] == reporterBox[m]) {
                        fl = 1;
                        break;
                    }
                }
                if (fl == 0) {
                    combo_reporter->addItem(dyeInfo["name"]);
                    reporterBox.append(dyeInfo["name"]);
                }

                // 判断淬灭基因名字是否重复，不重复则添加
                int fll = 0;
                for (int m = 0; m < quencherBox.length(); m++) {
                    if (dyeInfo["name"] == quencherBox[m]) {
                        fll = 1;
                        break;
                    }
                }
                if (fll == 0) {
                    combo_quencher->addItem(dyeInfo["name"]);
                    quencherBox.append(dyeInfo["name"]);
                }
            }
            if (dyeInfo["type"] == "报告基因") {
                // 判断报告基因名字是否重复，不重复则添加
                int fl = 0;
                for (int m = 0; m < reporterBox.length(); m++) {
                    if (dyeInfo["name"] == reporterBox[m]) {
                        fl = 1;
                        break;
                    }
                }
                if (fl == 0) {
                    combo_reporter->addItem(dyeInfo["name"]);
                    reporterBox.append(dyeInfo["name"]);
                }
            }
            if (dyeInfo["type"] == "淬灭基因") {
                // 判断淬灭基因名字是否重复，不重复则添加
                int fll = 0;
                for (int m = 0; m < quencherBox.length(); m++) {
                    if (dyeInfo["name"] == quencherBox[m]) {
                        fll = 1;
                        break;
                    }
                }
                if (fll == 0) {
                    combo_quencher->addItem(dyeInfo["name"]);
                    quencherBox.append(dyeInfo["name"]);
                }
            }
        }
    }

    // 设置下拉框的值
    for (int l = 0; l < ui->targetList->rowCount(); l++) {
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, l, 4);

        combo_reporter->clear();
        combo_quencher->clear();

        for (int m = 0; m < reporterBox.length(); m++) {
            combo_reporter->addItem(reporterBox[m]);
        }

        for (int m = 0; m < quencherBox.length(); m++) {
            combo_quencher->addItem(quencherBox[m]);
        }

        combo_reporter->setCurrentText(reporterName[l]);
        combo_quencher->setCurrentText(quencherName[l]);
    }

    // 快速设置参比荧光
    if (ui->targetList->rowCount() > 0) {
        ui->yingguangLine->clear();
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, 0, 3);

        for (int i = 0; i < combo_reporter->count(); i++) {
            ui->yingguangLine->addItem(combo_reporter->itemText(i));
        }

        ui->yingguangLine->setCurrentText("ROX");
    }

    // 更新和渲染视图
    updateTarget();
    renderDetailTable();
}

/* 孔位表右键打印功能 */
void ExperimentPlateUi::slotActionSave() {
    QString strFile = "孔位信息" + QDateTime::currentDateTime().toString("yyyyMMddHHmmss") + ".png";
    QPixmap pix = QPixmap::grabWidget(ui->sampleTable);

    QString fileName = QFileDialog::getSaveFileName(this, "保存图片", strFile,
                                                    "PNG (*.png);;BMP (*.bmp);;JPEG (*.jpg *.jpeg)");
    if (!fileName.isNull()) {
        pix.save(fileName);
    }
}

/* 点击快速设置页重新渲染靶基因和样本下拉框 */
void ExperimentPlateUi::rapidComboxChange(int index) {
    if (index == 0) {
        updateSample();
        updateTarget();
    }
}

/* 标准品界面绘制标准曲线功能 */
void ExperimentPlateUi::paintStand() {
    int count = stand->ui->countLine->text().toInt(); // 点数(纵轴点数)
    double yaxis[count]; // y轴点数对应数据
    double tcount = stand->ui->startLine->text().toDouble(); // 起始定量值(纵轴起始值)
    double xcount = 1; // 默认稀释比例
    // 设置稀释比例
    xcount = ratioMap[stand->ui->yBox->currentText()];


    yaxis[0] = tcount; // 起始定量值
    // 计算纵轴点数对应数据
    for (int i = 1; i < count; i++) {
        yaxis[i] = yaxis[i - 1] * xcount;
    }

    // 拼凑折线图和散点图, 绘制标准曲线
    chart = new QChart();
    auto *series = new QLineSeries; // 折线图
    auto *scatterSeries = new QScatterSeries(chart); // 散点图


    // 设置折线图和散点图数据点
    for (int l = 0; l < count; l++) {
        series->append(l + 1, count - l);
        scatterSeries->append(l + 1, count - l);
    }
    // 添加折线图和散点图到chart中
    chart->addSeries(series);
    chart->addSeries(scatterSeries);

    // 设置散点图中的点的大小为15
    scatterSeries->setMarkerSize(15);

    // 设置主题和图例隐藏
    chart->setTheme(QChart::ChartThemeQt);
    chart->legend()->hide();

    // 设置横轴和纵轴的范围
    QCategoryAxis *x = new QCategoryAxis();
    QCategoryAxis *y = new QCategoryAxis();
    x->setRange(0, count + 1);
    y->setRange(0, count + 1);

    // 向纵轴添加稀释后的数值
    for (int l = 0; l < count; l++) {
        y->append(QString::number(yaxis[l]), l + 1);
    }

    // 设置纵轴的标签位置为在数值上
    y->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue);

    // 设置横纵轴的散点图和折线图
    chart->setAxisX(x, series);
    chart->setAxisX(x, scatterSeries);

    chart->setAxisY(y, series);
    chart->setAxisY(y, scatterSeries);

    // 设置图表
    stand->ui->paint->setChart(chart);
}

/* 默认样本 */
void ExperimentPlateUi::defaultSample() {
    // 读取配置文件获取默认样本
    QString path = QCoreApplication::applicationDirPath();
    char *filePath;
    QByteArray tempByte = (path + "/" + CONFIG_FILE_NAME).toLocal8Bit();
    filePath = tempByte.data();
    Simplexml *simplexml = new Simplexml(filePath);
    simplexml->next("reaction-plate");

    QList<Sample> defaultSamples;

    for (int i = 0; i < 3; i++) {
        Sample sample;
        sample.name = QString::fromStdString(
                    simplexml->child("default-samples")->child("sample", i)->child("name")->text());
        defaultSamples.append(sample);
    }

    // 设置默认样本
    for (int l = 0; l < defaultSamples.length(); l++) {
        int samplerow = ui->sampleList->rowCount();

        ui->sampleList->setRowCount(samplerow + 1);

        QTableWidgetItem *check = new QTableWidgetItem();
        check->setCheckState(Qt::Unchecked);

        QString strname = defaultSamples[l].name;
        QTableWidgetItem *name = new QTableWidgetItem(strname);
        QColor qc = selectColor(flag[3], 1);
        QString strcolor;
        QTableWidgetItem *color = new QTableWidgetItem(strcolor);
        color->setBackgroundColor(qc);

        QString strexplain = "";
        QTableWidgetItem *explain = new QTableWidgetItem(strexplain);

        ui->sampleList->setItem(flag[3], 0, check);
        ui->sampleList->setItem(flag[3], 1, color);
        ui->sampleList->setItem(flag[3], 2, name);
        ui->sampleList->setItem(flag[3], 3, explain);

        QTableWidgetItem *itemc = ui->sampleList->item(flag[3], 1);
        itemc->setFlags(itemc->flags() & (~Qt::ItemIsEditable));
        itemc->setFlags(itemc->flags() & (~Qt::ItemIsSelectable));

        flag[3]++;
        flag[5]++;
    }
    // 更细样本
    updateSample();
}

/* 默认靶基因 */
void ExperimentPlateUi::defaultTarget() {
    // 从配置文件获取默认染料
    QList<QString> reporterBox;
    QList<QString> quencherBox;

    for (auto &l: dyeFromConfig) {
        if (l["type"] == "报告基因") {
            reporterBox.append(l["name"]);
        } else if (l["type"] == "淬火基因") {
            quencherBox.append(l["name"]);
        }
    }

    // 设置默认染料
    for (int l = 0; l < reporterBox.length(); l++) {
        int targetrow = ui->targetList->rowCount();

        ui->targetList->setRowCount(targetrow + 1);

        QTableWidgetItem *check = new QTableWidgetItem();
        check->setCheckState(Qt::Unchecked);

        QString strname = "Target" + QString::number(flag[4] + 1);;

        for (int i = 0; i < targetName.length(); i++) {
            if (strname == targetName[i]) {
                flag[4]++;
                strname = "Target" + QString::number(flag[4] + 1);
                break;
            }
        }

        QTableWidgetItem *name = new QTableWidgetItem(strname);

        targetName.append(strname);

        QComboBox *reporter = new QComboBox();
        reporter->setStyleSheet(style);
        for (int m = 0; m < reporterBox.length(); m++) {
            reporter->addItem(reporterBox[m]);
        }
        reporter->setCurrentText(reporterBox[l]);

        QComboBox *quencher = new QComboBox();
        quencher->setStyleSheet(style);
        for (int m = 0; m < quencherBox.length(); m++) {
            quencher->addItem(quencherBox[m]);
        }

        QString strexplain;
        QTableWidgetItem *explain = new QTableWidgetItem(strexplain);

        QComboBox *type = new QComboBox();
        type->setStyleSheet(style);
        for (int m = 0; m < targetTypeFromConfig.length(); m++) {
            type->addItem(targetTypeFromConfig[m]);
        }

        QColor qc = selectColor(flag[2], 2);
        // 如果报告基因为下述几个基因，则设置为固定颜色
        /* 当报告基因为FAM 或SYBR 或Green时为蓝色 */
        if(reporterBox[l] == "FAM"
                || reporterBox[l] == "SYBR"
                || reporterBox[l] == "Green"){
            qc = selectColor(0, 2);

        }
        /* 当报告基因为CY5 或LIZ时为红色 */
        else if(reporterBox[l] == "CY5"
                 || reporterBox[l] == "LIZ"){
            qc = selectColor(1, 2);

        }
        /* 当报告基因为VIC或HEX或TET或JOE时为绿色 */
        else if(reporterBox[l] == "VIC"
                 || reporterBox[l] == "HEX"
                 || reporterBox[l] == "JOE"
                 || reporterBox[l] == "TET"){
            qc = selectColor(2, 2);
        }
        /* 当报告基因为ROX或TexasRed时为黄色 */
        else if(reporterBox[l] == "ROX"
                 || reporterBox[l] == "TexasRed"){
            qc = selectColor(3, 2);
        }

        QString strcolor;
        QTableWidgetItem *color = new QTableWidgetItem(strcolor);
        color->setBackgroundColor(qc);

        QTableWidgetItem *quantity = new QTableWidgetItem();
        quantity->setFlags(quantity->flags() & 33);

        ui->targetList->setItem(flag[2], 0, check);
        ui->targetList->setItem(flag[2], 1, color);
        ui->targetList->setItem(flag[2], 2, name);
        ui->targetList->setCellWidget(flag[2], 3, reporter);
        ui->targetList->setCellWidget(flag[2], 4, quencher);
        ui->targetList->setCellWidget(flag[2], 5, type);
        ui->targetList->setItem(flag[2], 6, quantity);
        ui->targetList->setItem(flag[2], 7, explain);
        QTableWidgetItem *item = ui->targetList->item(flag[2], 1);
        item->setFlags(item->flags() & (~Qt::ItemIsEditable));
        item->setFlags(item->flags() & (~Qt::ItemIsSelectable));


        flag[2]++;
        flag[4]++;
        // 设置报告基因淬灭基因和类型更改的connect
        connect(reporter, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateTable(int)));
        connect(quencher, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateTable(int)));
        connect(type, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateTable(int)));
    }

    // 更新和渲染视图
    updateTarget();
    updateTargetListInfo();
}

/* 标准品界面模式选择功能 */
void ExperimentPlateUi::slotMode(int in) {
    // 遍历所有的靶基因，将其颜色设置为黑色
    for (int i = 0; i < stand->ui->target->count(); i++) {
        stand->ui->target->setItemData(i, QColor(Qt::black), Qt::ForegroundRole);
    }

    // 设置孔位行标签
    stand->ui->tableWidget->clear();
    stand->ui->tableWidget->setVerticalHeaderLabels(
                QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");
    standTargetName.clear();
    standTargetReporter.clear();
}

/* 标准品界面靶基因选择功能 */
void ExperimentPlateUi::slotTarget(int in) {
    // 获取选中的靶基因 及 反应板行列数
    QString targetName = stand->ui->target->currentText();
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();

    // 单重模式
    if (stand->ui->mode->currentText() == "单重") {
        // 设置靶基因名称
        standTargetName.clear();
        standTargetReporter.clear();
        standTargetName.append(targetName);

        // 选中的靶基因标红
        for (int l = 0; l < stand->ui->target->count(); l++) {
            if (stand->ui->target->itemText(l) == targetName) {
                stand->ui->target->setItemData(l, QColor(Qt::red), Qt::ForegroundRole);
            } else {
                stand->ui->target->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
            }
        }

        // 设置报告基因
        for (int l = 0; l < ui->targetList->rowCount(); l++) {
            if (targetName == ui->targetList->item(l, 2)->text()) {
                QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
                QString string_reporter = combo_reporter->currentText();

                standTargetReporter.append(string_reporter);
                break;
            }
        }

        // 1 列 2 行 3 自动选择 4 手动选择
        // 列自动选择
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_3->isChecked()) {

            setStandLayout(row, column, true, false, true, true, false, true, false);
        }

        // 行自动选择
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_3->isChecked()) {
            setStandLayout(row, column, false, false, true, true, false, true, false);
        }

        // 列手动选择
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_4->isChecked()) {
            // 获取被选中的孔位
            QItemSelectionModel *selection = stand->ui->tableWidget->selectionModel();
            QModelIndexList indexList = selection->selectedIndexes();
            // 遍历被选中的孔位
            foreach(QModelIndex index, indexList) {
                // 设置布局
                widgetLabel = createLabelWidget();
                // 设置反应板报告基因
                // 调用函数，创建并添加标准品信息的标签
                createAndAddReporterLabel();
                // 设置反应板孔位
                stand->ui->tableWidget->setCellWidget(index.row(), index.column(), widgetLabel);
            }
        }

        // 行手动选择
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_4->isChecked()) {
            // 获取被选中的孔位
            QItemSelectionModel *selection = stand->ui->tableWidget->selectionModel();
            QModelIndexList indexList = selection->selectedIndexes();
            // 遍历被选中的孔位
            foreach(QModelIndex index, indexList) {
                // 设置布局
                widgetLabel = createLabelWidget();
                // 设置反应板报告基因
                QString reporter = standTargetReporter[0];
                QLabel *label = new QLabel();
                label->setText(reporter);
                vLayout->addWidget(label);
                // 设置反应板孔位
                stand->ui->tableWidget->setCellWidget(index.row(), index.column(), widgetLabel);
            }
        }
    }

    // 多重模式
    if (stand->ui->mode->currentText() == "多重") {
        // 设置靶基因名称
        standTargetName.append(targetName);

        // 判断报告基因是否已经添加
        QString targetReporter;
        int flag = 0;
        for (int l = 0; l < ui->targetList->rowCount(); l++) {
            if (targetName == ui->targetList->item(l, 2)->text()) {
                QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
                QString string_reporter = combo_reporter->currentText();
                targetReporter = string_reporter;

                for (int k = 0; k < standTargetReporter.length(); k++) {
                    if (standTargetName[k] != ui->targetList->item(l, 2)->text() &&
                            standTargetReporter[k] == string_reporter) {
                        cusMsg->show(stand, CMsg::CWarning, "提示", "报告基因重复，请重新选择");
                        flag = 1;
                        break;
                    }
                    if (standTargetName[k] == ui->targetList->item(l, 2)->text()) {
                        cusMsg->show(stand, CMsg::CWarning, "提示", "该靶基因已添加");
                        flag = 1;
                        break;
                    }
                }
                break;
            }
        }

        // 添加报告基因到反应板
        if (flag == 0) {
            standTargetReporter.append(targetReporter);
        }

        // 1 列 2 行 3 自动选择 4 手动选择
        // 列自动选择
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_3->isChecked()) {
            setStandLayout(row, column, true, false, true, false, true, true, false);
        }

        // 行自动选择
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_3->isChecked()) {

            setStandLayout(row, column, false, false, true, false, true, true, false);

        }

        // 列手动选择
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_4->isChecked()) {
            // 获取被选中的孔位
            QItemSelectionModel *selection = stand->ui->tableWidget->selectionModel();
            QModelIndexList indexList = selection->selectedIndexes();
            // 遍历被选中的孔位
            foreach(QModelIndex index, indexList) {
                // 设置布局
                widgetLabel = createLabelWidget();
                // 设置反应板报告基因
                for (int l = 0; l < standTargetReporter.length(); l++) {
                    QString reporter = standTargetReporter[l];
                    QLabel *label = new QLabel();
                    label->setText(reporter);
                    vLayout->addWidget(label);
                }
                // 设置反应板孔位
                stand->ui->tableWidget->setCellWidget(index.row(), index.column(), widgetLabel);
            }
        }

        // 行手动选择
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_4->isChecked()) {
            // 获取被选中的孔位
            QItemSelectionModel *selection = stand->ui->tableWidget->selectionModel();
            QModelIndexList indexList = selection->selectedIndexes();
            // 遍历被选中的孔位
            foreach(QModelIndex index, indexList) {
                // 设置布局
                widgetLabel = createLabelWidget();
                // 设置反应板报告基因
                for (int l = 0; l < standTargetReporter.length(); l++) {
                    QString reporter = standTargetReporter[l];
                    QLabel *label = new QLabel();
                    label->setText(reporter);
                    vLayout->addWidget(label);
                }
                // 设置反应板孔位
                stand->ui->tableWidget->setCellWidget(index.row(), index.column(), widgetLabel);

            }
        }

        // 设置靶基因颜色
        for (int l = 0; l < stand->ui->target->count(); l++) {
            for (int k = 0; k < standTargetName.length(); k++) {
                if (stand->ui->target->itemText(l) == standTargetName[k]) {
                    stand->ui->target->setItemData(l, QColor(Qt::red), Qt::ForegroundRole);
                }
            }
        }
    }
}

/* 初始化耗材表 */
void ExperimentPlateUi::startMaterial() {
    for (auto i: ui->widget_4->children()) {
        if (i->objectName() != "materialCircle16") { // widget_4中除了materialCircle16的都是按钮
            auto *button = qobject_cast<QPushButton *>(i); // 将QObject转换为QPushButton
            if (button) { // 如果转换成功
                button->setEnabled(true); // 调用setEnabled方法
                button->setStyleSheet(
                            "QPushButton {\ color: #fff;\ font-weight: bold;\ font-family: \"Alibaba PuHuiTi\";\ background: #9d9d9d;\ border-radius: 7px;\ }");
            }
        }
    }
    for (auto i: ui->widget_5->children()) {
        if (i->objectName() != "materialCircle32") {
            auto *button = qobject_cast<QPushButton *>(i); // 将QObject转换为QPushButton
            if (button) { // 如果转换成功
                button->setEnabled(true); // 调用setEnabled方法
                button->setStyleSheet(
                            "QPushButton {\ color: #fff;\ font-weight: bold;\ font-family: \"Alibaba PuHuiTi\";\ background: #9d9d9d;\ border-radius: 7px;\ }");
            }
        }
    }

    /* 渲染耗材类型界面孔位标识 */
    renderDataLabel();
}

/* 反应板下方样本类型和空闲孔位 */
void ExperimentPlateUi::markTable() {
    // 获取反应板样本数量
    sampleCount = 0;
    for (auto &m: reactionPlate.sampleList) {
        if (m.name != "null") {
            sampleCount++;
        }
    }

    // U S N 存储样本类型
    int typeName[3] = {0, 0, 0};
    // 尝试不适用临时变量
    // 临时变量
    //    int count[3] = {0, 0, 0};

    // 当前选择的耗材类型的索引, 获取孔位数量
    int index = ui->materialType->currentIndex();
    int allIndex = 0;
    if (index == 0) {
        allIndex = 16;
    } else if (index == 1) {
        allIndex = 32;
    }
    // // 计算样本类型数量
    // for (int i = 0; i < allIndex; i++) {
    //     // 清空临时变量count
    //     //        for (int & c : count) {
    //     //            c = 0;
    //     //        }
    //     for (int j = 0; j < 20; j++) {
    //         //            if (reactionPlate.targetList[i][j].type == "unknown(未知)" && count[0] == 0) {
    //         if (reactionPlate.targetList[i][j].type == "unknown(未知)") {
    //             typeName[0]++;
    //         //                count[0]++;
    //         }
    //         if (reactionPlate.targetList[i][j].type == "stander(标准)") {
    //             typeName[1]++;
    //         }
    //         if (reactionPlate.targetList[i][j].type == "NTC") {
    //             typeName[2]++;
    //         }
    //     }
    // }
    // 计算样本类型数量
    for (int i = 0; i < allIndex; i++) {
        int uCount = 0;
        int sCount = 0;
        int nCount = 0;
        for (int j = 0; j < 20; j++) {
            //            LOG << reactionPlate.targetList[i][j].type;
            if (reactionPlate.targetList[i][j].type.contains("known")) { // 未知
                uCount++;
            }
            else if (reactionPlate.targetList[i][j].type.contains("and")){ // 标准
                sCount++;
            }
            else if (reactionPlate.targetList[i][j].type.contains("NTC")) { // NTC
                nCount++;
            }
        }
        //        LOG << uCount << " " << sCount << " " << nCount;
        if (uCount > 0) {
            typeName[0]++;
        }
        if (sCount > 0) {
            typeName[1]++;
        }
        if (nCount > 0) {
            typeName[2]++;
        }
    }

    //     LOG << "unknown(未知)" << typeName[0] << " stander(标准):" << typeName[1] << " NTC:" << typeName[2];


    // 计算反应板内空闲的孔位个数，在反应板下方的label显示
    int free = allIndex - sampleCount;
    if (free < 0) { free = 0; }
    // 设置 U S N 数值
    if (typeName[0] > allIndex) { typeName[0] = allIndex; }
    if (typeName[1] > allIndex) { typeName[1] = allIndex; }
    if (typeName[2] > allIndex) { typeName[2] = allIndex; }
    ui->sampleInfoLabel->setText("U:" + QString::number(typeName[0]) + " S:" + QString::number(typeName[1]) + " N:" +
            QString::number(typeName[2]) + "    空闲孔位: " + QString::number(free));

}

/**
 * @brief           按顺序返回样本颜色
 * @param number    flag[3]: 样本个数 flag[2]: 靶基因个数
 * @param int       mode 1: 样本颜色 2: 靶基因颜色
 * @return          QColor
 */
QColor ExperimentPlateUi::selectColor(int number, int mode) {
    if (mode == 1) {
        int rgbNum[13][3] = {{255, 188, 188},
                             {255, 204, 153},
                             {255, 255, 173},
                             {153, 255, 204},
                             {214, 255, 173},
                             {204, 255, 229},
                             {153, 255, 255},
                             {153, 204, 255},
                             {204, 204, 255},
                             {204, 153, 255},
                             {255, 204, 255},
                             {255, 153, 204},
                             {224, 224, 224}};

        int index = number % 13;

        QColor sampleColor;
        sampleColor.setRed(rgbNum[index][0]);
        sampleColor.setGreen(rgbNum[index][1]);
        sampleColor.setBlue(rgbNum[index][2]);

        return sampleColor;

    } else {
        int rgbNum[13][3] = {{0, 0, 255},
                             {255, 0, 0},
                             {0, 255, 0},
                             {255,124,0},
                             {255, 0, 255},
                             {128, 0, 0},
                             {127, 255, 0},
                             {0, 255, 255},
                             {0, 0, 128},
                             {255, 127, 80},
                             {184, 116, 51},
                             {138, 43, 226},
                             {0, 250, 154}};

        int index = number % 13;

        QColor sampleColor;
        sampleColor.setRed(rgbNum[index][0]);
        sampleColor.setGreen(rgbNum[index][1]);
        sampleColor.setBlue(rgbNum[index][2]);

        return sampleColor;
    }

}

/* 更新table样本类型和Detail Table样本类型 */
void ExperimentPlateUi::updateTable() {
    // 遍历所有孔位
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 12; j++) {
            // 设置布局
            vLayout = new QVBoxLayout();
            widgetLabel = new QWidget();
            gLayout = new QGridLayout();

//            widgetLabel = createLabelWidget();

            // 计算反应板对应孔位的位置编号
            int count = 8 * j + i;
            // 反应板信息过滤
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                QString strname = reactionPlate.sampleList[count].name;

                if (strname != "null") {
                    if (copySampleName[count] != "") {
                        strname = copySampleName[count];
                    }

                    QLabel *label = createLabel(strname);
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);

                    // 将颜色值转换为十六进制字符串
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    // 设置标签的背景颜色
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));

                    label->resize(static_cast<int>(strlen(reinterpret_cast<char *>(label->text().data()))) *
                                  label->font().pointSize(), 24);
                    label->setFixedHeight(22);

                    vLayout->addWidget(label);
                }
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                    !ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                QString name = reactionPlate.sampleList[count].name;

                if (name != "null") {
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                    QLabel *label = createLabel(name);
                    label->resize(static_cast<int>(strlen(reinterpret_cast<char *>(label->text().data()))) *
                                  label->font().pointSize(), 24);
                    //                    label->setFixedHeight(22);

                    //                    label->setFixedHeight(22);
                    vLayout->addWidget(label);
                }
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    !ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                QString name = reactionPlate.sampleList[count].name;

                if (name != "null") {
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    QLabel *label = new QLabel();
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    vLayout->addWidget(label);
                }
            }

            int p = 0;
            for (int l = 0; l < 20; l++) {
                if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                        ui->tableFilter->menu()->actions().value(1)->isChecked()) {
                    if (reactionPlate.targetList[count][l].reporter != "null") {
                        createTargetLabel(reactionPlate, count, l, p, false);
                    }
                }
            }


            // 设置布局和样式
            gLayout->setSpacing(0);
            gLayout->setMargin(0);
            vLayout->addLayout(gLayout);
            widgetLabel->setLayout(vLayout);
            ui->sampleTable->setCellWidget(i, j, widgetLabel);
        }

    }
    // 更新和渲染孔位信息表格
    renderDetailTable();

}

/* 从配置文件中读取靶基因类型，耗材类型， 染料库信息*/
void ExperimentPlateUi::readFromXML() {
    targetTypeFromConfig = configService->getTargetType();
    consumableFromConfig = configService->getConsumablesType();
    dyeFromConfig = configService->getDyes();
}

/**
 * @brief 根据从配置文件中读取的耗材类型渲染表格
 * @param QString consumable 耗材类型
 */
bool ExperimentPlateUi::readAndRenderTableRowColumnFromXML(QString consume) {
    LOG << "consume: " << consume;
    // 读取配置文件
    reactionPlate.consumables = consume;
    sampleTableRowColumn = configService->getRowAndColByConsumableType(consume);

    LOG << "sampleTableRowColumn" << sampleTableRowColumn[0] << sampleTableRowColumn[1];

    // 反应板行列数
    int row = sampleTableRowColumn[0];
    int column = sampleTableRowColumn[1];

    // 反应板列数不符
    LOG << "row: " << row;
    if (row != 8) {
        column = 2;
        row = 8;
        LOG << "row: " << row;
        cusMsg->show(this, CMsg::CCritical, "错误", "导出的数据文件与现版本不符，请导入新实验数据");
        LOG << "不符合";
        emit ExperimentPlateUi::closePage();
        return false;
    }

    // 设置标准品
    if (column == 2) {
        stand->tableFlag = 0;
    }
    if (column == 4) {
        stand->tableFlag = 1;
    }

    ui->sampleTable->blockSignals(true);
    /* 渲染sampleTable */
    ui->sampleTable->clear();
    ui->sampleTable->setVerticalHeaderLabels(QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");
    for (int m = 0; m < row; m++) {
        for (int n = column; n < 12; n++) {
            QTableWidgetItem *newItem = new QTableWidgetItem();
            //            newItem->setFlags(newItem->flags() & ~Qt::ItemIsSelectable);
            ui->sampleTable->setItem(m, n, newItem);
            //            QTableWidgetItem *item = ui->sampleTable->item(m, n);
            //            item->setFlags(item->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
            ui->sampleTable->setColumnHidden(n, true);
        }
    }
    for (int m = 0; m < row; m++) {
        for (int n = 0; n < column; n++) {
            ui->sampleTable->setColumnHidden(n, false);
        }
    }

    LOG << "反应板2222";

    /* 渲染detailTable */
    QList<QString> reporterBox;
    QList<QString> quencherBox;

    for (int l = 0; l < dyeFromConfig.length(); l++) {
        if (dyeFromConfig[l]["type"] == "报告基因") {
            reporterBox.append(dyeFromConfig[l]["name"]);
        } else if (dyeFromConfig[l]["type"] == "淬火基因") {
            quencherBox.append(dyeFromConfig[l]["name"]);
        }
    }

    int allRow = reporterBox.length() * column * row;
    ui->detailTable->setRowCount(allRow);
    for (int l = 0; l < allRow; l++) {
        ui->detailTable->takeItem(l, 1);
        ui->detailTable->takeItem(l, 2);
        ui->detailTable->takeItem(l, 3);
        ui->detailTable->takeItem(l, 4);
        ui->detailTable->takeItem(l, 5);
    }
    for (int l = 0; l < column * row; l++) {
        int acolumn = l / row;
        int arow = l % row;
        for (int i = 0; i < detailReporterBox.length(); i++) {
            // 调用createItem()函数创建一个表格项
            QTableWidgetItem *item = createItem(arow, acolumn);
            ui->detailTable->setItem(l * detailReporterBox.length() + i, 0, item);
        }
    }

    LOG << "反应板5555";
    ui->sampleTable->blockSignals(false);
}

/* 实验初始化 */
void ExperimentPlateUi::startExpe() {
    /* 隐藏组件 */
    hideComponents();

    /* 实例化 */
    createObjects();

    /* 初始化相关数据 */
    initData();

    /* 从配置文件读取反应板相关数据 */
    readFromXML();

    /* 反应版耗材图片设置 */
    QImage *guanShi32 = new QImage(); // 管式32
    QImage *xinPian16 = new QImage(); // 芯片16
    // 加载图片
    guanShi32->load(":image/image/maierial_1.png"); // 管式32
    xinPian16->load(":image/image/maierial_3.png"); // 芯片16
    // 渲染图片
    ui->materialCircle32->setPixmap(QPixmap::fromImage(guanShi32->scaled(400, 400, Qt::KeepAspectRatio, Qt::SmoothTransformation))); // 管式32
    ui->materialCircle16->setPixmap(QPixmap::fromImage(xinPian16->scaled(400, 400, Qt::KeepAspectRatio, Qt::SmoothTransformation))); // 芯片16

    /* 初始化快速设置sample表格 */
    ui->sample->setCurrentIndex(-1);
    //    ui->sample->setEditable(true);
    ui->sample->setLineEdit(sampleEdit);

    /* 设置耗材图片页标识label自动换行 */
    ui->dataLabel32->setWordWrap(true);

    /* 初始化样本标识 */
    ui->sampleInfoLabel->setText(
                "U:" + QString::number(0) + " S:" + QString::number(0) + " N:" + QString::number(0) + "    空闲孔位: " +
                QString::number(16));

    /* 设置sample中QLineEdit样式 */
    sampleEdit->setStyleSheet(
                "\QLineEdit {\font-size: 18px;\font-family: \"Alibaba PuHuiTi\";\background: transparent;\border: none;\}");


    ui->sampleTable->setEditTriggers(QAbstractItemView::NoEditTriggers);

    ui->detailTable->setEditTriggers(QAbstractItemView::NoEditTriggers);


    /* 根据配置文件动态设置耗材类型下拉框 */
    for (int i = 0; i < consumableFromConfig.length(); i++) {
        ui->materialType->addItem(consumableFromConfig[i]);
    }

    /* 设置耗材类型默认值 */
    ui->materialType->setCurrentIndex(0);
    reactionPlate.consumables = ui->materialType->currentText();

    /* 根据耗材类型设置样板表格式 */
    LOG <<"1";
    readAndRenderTableRowColumnFromXML(consumableFromConfig[0]);

    // 清空反应板信息
    clearPlateInformation();

    /* 初始化复制信息 */
    copyNameReporter.sampleName.name = "null";
    copyNameReporter.sampleName.color_value = "null";
    copyNameReporter.sampleName.remarks = "null";
    for (int i = 0; i < 4; i++) {
        copyNameReporter.targetReporter[i].reporter = "null";
        copyNameReporter.targetReporter[i].name = "null";
        copyNameReporter.targetReporter[i].type = "null";
        copyNameReporter.targetReporter[i].quencher = "null";
        copyNameReporter.targetReporter[i].quantity = "null";
        copyNameReporter.targetReporter[i].color = "null";
        copyNameReporter.targetReporter[i].explain = "null";
    }

    /* 初始化标准品表格数据 */
    standTargetName.clear();
    standTargetReporter.clear();

    /* 初始化标准品表格渲染数据 */
    for (int i = 0; i < 96; i++) {
        standIndex[i] = 0;
    }

    /* 添加高级设置默认样本 */
    defaultSample();

    /* 添加高级设置默认靶基因 */
    defaultTarget();

    /* 初始化耗材表图片 */
    startMaterial();

    /* 渲染参比荧光下拉框 */
    renderyingguangLine();


    /* 添加查看过滤下拉框及其功能 */
    menu = new QMenu();
    action_1 = new QAction(tr("&样本名称"));
    action_3 = new QAction(tr("&靶基因"));
    action_2 = new QAction(tr("&样本颜色"));
    action_1->setCheckable(true);
    action_3->setCheckable(true);
    action_2->setCheckable(true);
    action_1->setChecked(true);
    action_3->setChecked(true);
    action_2->setChecked(true);
    menu->addAction(action_1);
    menu->addAction(action_3);
    menu->addAction(action_2);
    ui->tableFilter->setMenu(menu);

    /* QMenu样式 */
    menu->setStyleSheet(
                "QMenu::item{" "width: 107px;" "font-size: 20px;" "font-family: 'Alibaba PuHuiTi';" "padding: 5px;" "}" "QMenu::item::selected {" "color: #000;" "border: none;" "background: rgba(75, 154, 250, 0.2);" "}");

    /* 设置表格样式 */
    QHeaderView *horizontalHeaderTable = ui->sampleTable->horizontalHeader();
    horizontalHeaderTable->setSectionResizeMode(QHeaderView::Stretch);
    horizontalHeaderTable->setDefaultAlignment(Qt::AlignCenter);
    horizontalHeaderTable->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;height:32px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");

    QHeaderView *verticalHeader = ui->sampleTable->verticalHeader();
    verticalHeader->setSectionResizeMode(QHeaderView::Stretch);
    verticalHeader->setDefaultAlignment(Qt::AlignCenter);
    verticalHeader->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;width:23px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");
    //    ui->detailTable->resizeRowsToContents();
    //    ui->detailTable->resizeColumnsToContents();
    //    ui->detailTable->horizontalHeaderTable()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->detailTable->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter);
    ui->detailTable->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
    ui->detailTable->horizontalHeader()->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;height:32px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");
    ui->detailTable->verticalHeader()->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;width:23px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");
    //    QHeaderView::section::first{border-left:1px solid #000;}
    //    LOG << "宽度:" << ui->sampleTable->horizontalHeaderTable()->height() << ui->sampleTable->verticalHeader()->isVisible();

    QHeaderView *horizontalHeaderList = ui->sampleList->horizontalHeader();
    horizontalHeaderList->setSectionResizeMode(QHeaderView::Stretch);
    horizontalHeaderList->setSectionResizeMode(0, QHeaderView::Fixed);
    horizontalHeaderList->setSectionResizeMode(1, QHeaderView::Fixed);
    horizontalHeaderList->setSectionResizeMode(2, QHeaderView::Fixed);
    horizontalHeaderList->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;height:32px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");
    horizontalHeaderList->setDefaultAlignment(Qt::AlignCenter);

    ui->sampleList->setColumnWidth(0, 20);
    ui->sampleList->setColumnWidth(1, 20);
    ui->sampleList->setColumnWidth(2, 400);
    ui->sampleList->verticalHeader()->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;width:23px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");
    ui->sampleList->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);

    QHeaderView *horizontalHeaderTargetList = ui->targetList->horizontalHeader();
    horizontalHeaderTargetList->setSectionResizeMode(QHeaderView::Stretch);
    horizontalHeaderTargetList->setSectionResizeMode(0, QHeaderView::Fixed);
    horizontalHeaderTargetList->setSectionResizeMode(1, QHeaderView::Fixed);
    horizontalHeaderTargetList->setSectionResizeMode(5, QHeaderView::Fixed);
    horizontalHeaderTargetList->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;height:32px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");
    horizontalHeaderTargetList->setDefaultAlignment(Qt::AlignCenter);

    ui->targetList->setColumnWidth(0, 20);
    ui->targetList->setColumnWidth(1, 20);
    ui->targetList->verticalHeader()->setStyleSheet(
                "QHeaderView::section{border:1px solid #000;border-top:none;border-left:none;width:23px;background:transparent;font-family:\"Alibaba PuHuiTi\";text-align:center;}");
    ui->targetList->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);

    ui->targetList->setColumnWidth(5, 150);

    ui->sampleTable->setMouseTracking(true);
    //   ui->sampleTable->installEventFilter(this);

    ui->sampleTable->setContextMenuPolicy(Qt::CustomContextMenu);
    tableMenu = new QMenu(ui->sampleTable);
    action_print = new QAction("打印", this);
    action_export = new QAction("导出excel", this);
    action_setting = new QAction("设置标准品", this);
    actionCopy = new QAction("复制", this);
    actionPaste = new QAction("粘贴", this);

    tableMenu->addAction(actionCopy);
    tableMenu->addAction(actionPaste);
    tableMenu->addAction(action_print);
    tableMenu->addAction(action_export);
    tableMenu->addAction(action_setting);

    ui->copyCount->setRange(1, 16);
    ui->startCount->setRange(1, 16);
    /* 设置样板表自动选中 */
    ui->sampleTable->setCurrentCell(0, 0);

    view->ui->countLineEdit->setValidator(new QRegExpValidator(
                                              QRegExp("^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$")));

    LOG << "反应板初始化结束";
}

/* 更新快速设置靶基因 */
void ExperimentPlateUi::updateTarget() {
    ui->target->clear();
    for (int m = 0; m < ui->targetList->rowCount(); m++) {
        ui->target->addItem(ui->targetList->item(m, 2)->text());
    }
}

/* 更新快速设置样本 */
void ExperimentPlateUi::updateSample() {
    /*清空sample的所有选项*/
    ui->sample->clear();
    for (int m = 0; m < ui->sampleList->rowCount(); m++) {
        ui->sample->addItem(ui->sampleList->item(m, 2)->text());
    }
    ui->sample->setCurrentIndex(-1);
}

/* 渲染耗材类型界面孔位标识: (A1 B2 C3 D4) */
void ExperimentPlateUi::renderDataLabel() {
    QString str16;
    QString str32;
    // 遍历孔位判断样本是否为空
    int picFlag[96];
    for (int l = 0; l < 96; l++) {
        if (reactionPlate.sampleList[l].name == "null") {
            picFlag[l] = 0;
        } else {
            picFlag[l] = 1;
        }
    }

    // 11*8+7=95
    for (int i = 0; i < 12; i++) {
        for (int j = 0; j < 8; j++) { // 行字母判断
            if (picFlag[i * 8 + j] == 1) {
                // 如果该孔位不为空
                QString label = rowLetters[j];

                // 获取列数字
                QString number = QString::number(i + 1);
                QString info = label + number + " ";
                if (i * 8 + j < 16) { // 芯片-16
                    str16.append(info);
                }
                if (i * 8 + j < 32) { // 管式
                    str32.append(info);
                }
            }
        }
    }

    ui->dataLabel16->setText("孔位信息:" + str16);
    ui->dataLabel32->setText("孔位信息:" + str32);
}

/* 表格转换为detailTable形式 */
void ExperimentPlateUi::slotGotoDetailTable() {
    /* 相关控件隐藏 */
    ui->gotoTable->show();
    ui->gotoMaterialTable->show();
    ui->detailTable->show();
    ui->tableFilter->show();
    ui->materialTable->hide();
    ui->matetialTable_1->hide();
    ui->sampleTable->hide();
    ui->gotoDetailTable->hide();
    ui->fullscreen->hide();
    ui->clearTable->hide();
    detailTableInfoRender();
//    ui->targetList->blockSignals(true);
    this->targetNumberNotClick();
}

/* 转至耗材图片 */
void ExperimentPlateUi::slotGotoMaterialTable() {
    ui->gotoTable->show();
    ui->gotoDetailTable->show();

    // 渲染样本孔
    renderMaterial();

    ui->detailTable->hide();
    ui->sampleTable->hide();
    ui->gotoMaterialTable->hide();
    ui->fullscreen->hide();
    ui->clearTable->hide();
    ui->tableFilter->hide();

    renderDataLabel();
    this->targetNumberNotClick();
}

/* 转换为表格形式 */
void ExperimentPlateUi::slotGotoTable() {
    ui->gotoDetailTable->show();
    ui->gotoMaterialTable->show();
    ui->fullscreen->show();
    ui->clearTable->show();
    ui->sampleTable->show();
    ui->tableFilter->show();
    ui->detailTable->hide();
    ui->materialTable->hide();
    ui->matetialTable_1->hide();
    ui->gotoTable->hide();
//    ui->targetList->blockSignals(false);
    this->targetNumberCanClick();
}

/* 反应版右部分向坐扩展 */
void ExperimentPlateUi::slotRightExpanding() {
    ui->plateRightPart->show();
    ui->leftExpending->show();
    ui->plateLeftPart->hide();
    ui->rightExpending->hide();
    ui->restore->show();
}

/* 反应版左部分向右扩展 */
void ExperimentPlateUi::slotLeftExpanding() {
    ui->plateLeftPart->show();
    ui->rightExpending->show();
    ui->plateRightPart->hide();
    ui->leftExpending->hide();
    ui->restore->show();
}

/* 恢复实验板布局 */
void ExperimentPlateUi::slotRestore() {
    ui->plateLeftPart->show();
    ui->plateRightPart->show();
    ui->rightExpending->show();
    ui->leftExpending->show();
    ui->restore->hide();
}

/* 高级设置：折叠样本面板 */
void ExperimentPlateUi::slotFoldSampleList() {
    ui->sampleListWidget->hide();
    ui->foldSampleList->hide();
    ui->extendSampleList->show();
}

/* 高级设置：展开样本面板 */
void ExperimentPlateUi::slotExtendSampleList() {
    ui->sampleListWidget->show();
    ui->foldSampleList->show();
    ui->extendSampleList->hide();
}

/* 高级设置：折叠靶基因面板 */
void ExperimentPlateUi::slotFoldTargetList() {
    ui->targetListWidget->hide();
    ui->foldTargetList->hide();
    ui->extendTargetList->show();
}

/* 高级设置：展开靶基因面板 */
void ExperimentPlateUi::slotExtendTargetList() {
    ui->targetListWidget->show();
    ui->foldTargetList->show();
    ui->extendTargetList->hide();
}

/* 将字符串转换成颜色对象 */
QColor ExperimentPlateUi::stringToColor(QString colorStr) {
    QColor color;
    QStringList rgb = colorStr.split(',');
    if (rgb.size() == 3) {
        int r = rgb.at(0).toInt();
        int g = rgb.at(1).toInt();
        int b = rgb.at(2).toInt();
        color.setRgb(r, g, b);
    } else
        color.setNamedColor(colorStr);

    return color;
}

/* 将颜色对象转换成字符串 */
QString ExperimentPlateUi::colorTostring(QColor color) {
    QString str = "";
    str = QString::number(color.red()) + "," + QString::number(color.green()) + "," + QString::number(color.blue());

    return str;
}

/* 孔位表全屏显示功能 */
void ExperimentPlateUi::slotFullScreen() {
    ui->tableFilter->hide();
    ui->clearTable->hide();
    ui->gotoTable->hide();
    ui->gotoMaterialTable->hide();
    ui->gotoDetailTable->hide();
    ui->fullscreen->hide();
    ui->normalScreen->show();
    ui->tableWidget->setWindowFlags(Qt::Window);
    ui->tableWidget->showFullScreen();
}

/* 孔位表恢复正常大小 */
void ExperimentPlateUi::slotNormalScreen() {
    ui->tableFilter->show();
    ui->clearTable->show();
    ui->gotoTable->hide();
    ui->gotoMaterialTable->show();
    ui->gotoDetailTable->show();
    ui->fullscreen->show();
    ui->normalScreen->hide();
    ui->tableWidget->setWindowFlags(Qt::SubWindow);
    ui->tableWidget->showNormal();
}

/* 渲染孔位信息表格 */
void ExperimentPlateUi::renderDetailTable() {
    // 反应板详细信息报告基因清空
    detailReporterBox.clear();
    // 从配置文件获取默认染料
    QList<QString> quencherBox;

    for (auto &l: dyeFromConfig) {
        if (l["type"] == "报告基因") {
            detailReporterBox.append(l["name"]);
        } else if (l["type"] == "淬火基因") {
            quencherBox.append(l["name"]);
        }
    }
    // 如果靶基因列表存在报告基因，存储到 反应板详细信息报告基因
    if (ui->targetList->rowCount() > 0) {
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, 0, 3);

        detailReporterBox.clear();
        for (int i = 0; i < combo_reporter->count(); i++) {
            detailReporterBox.append(combo_reporter->itemText(i));
        }
    }

    // 从配置文件中获取默认的反应板行列数
    int row = sampleTableRowColumn[0];
    int column = sampleTableRowColumn[1];

    // 反应板列数不符
    if (row != 8) {
        column = 2;
        row = 8;
    }

    // 反应板详细信息行数 = 报告基因数 * 反应板行数 * 反应板列数
    int allRow = detailReporterBox.length() * column * row;
    ui->detailTable->setRowCount(allRow);

    // 设置孔位名
    for (int l = 0; l < column * row; l++) {
        int acolumn = l / row;
        int arow = l % row;
        for (int i = 0; i < detailReporterBox.length(); i++) {
            // 调用createItem()函数创建一个表格项
            QTableWidgetItem *item = createItem(arow, acolumn);
            ui->detailTable->setItem(l * detailReporterBox.length() + i, 0, item);
        }
    }

    // Removes the item at row and column from the table without deleting it
    // 清空其他信息
    for (int l = 0; l < allRow; l++) {
        ui->detailTable->takeItem(l, 1);
        ui->detailTable->takeItem(l, 2);
        ui->detailTable->takeItem(l, 3);
        ui->detailTable->takeItem(l, 4);
        ui->detailTable->takeItem(l, 5);
    }

    // 设置其他信息
    for (int l = 0; l < column * row; l++) {
        for (int i = 0; i < 20; i++) {
            //             if(reactionPlate.targetList[l][i].name == "null"){
            //                 break;
            //             }
            if (reactionPlate.sampleList[l].name != "null") {
                QTableWidgetItem *name = new QTableWidgetItem(reactionPlate.sampleList[l].name);
                ui->detailTable->setItem(l * detailReporterBox.length() + i, 1, name);
            }
            if (reactionPlate.targetList[l][i].name != "null") {
                QTableWidgetItem *name = new QTableWidgetItem(reactionPlate.targetList[l][i].name);
                ui->detailTable->setItem(l * detailReporterBox.length() + i, 2, name);
            }
            if (reactionPlate.targetList[l][i].type != "null") {
                QTableWidgetItem *type = new QTableWidgetItem(reactionPlate.targetList[l][i].type);
                ui->detailTable->setItem(l * detailReporterBox.length() + i, 3, type);
            }
            if (reactionPlate.targetList[l][i].quantity != "null") {
                QTableWidgetItem *quantity = new QTableWidgetItem(reactionPlate.targetList[l][i].quantity);
                ui->detailTable->setItem(l * detailReporterBox.length() + i, 4, quantity);
            }
            if (reactionPlate.targetList[l][i].explain != "null") {
                QTableWidgetItem *explain = new QTableWidgetItem(reactionPlate.targetList[l][i].explain);
                ui->detailTable->setItem(l * detailReporterBox.length() + i, 5, explain);
            }
        }
    }
}

/*  渲染标准品界面表格 */
void ExperimentPlateUi::renderStandTable(QString consume) {

    // 设置表格的水平表头的调整模式为自动拉伸
    stand->ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    // 根据消耗品类型，获取样本表格的行和列
    sampleTableRowColumn = configService->getRowAndColByConsumableType(consume);
    int row = sampleTableRowColumn[0];
    int column = sampleTableRowColumn[1];

    // 如果列数是2，就设置标准表格的标志位为0
    if (column == 2) {
        stand->tableFlag = 0;
    }
    if (column == 4) {
        stand->tableFlag = 1;
    }

    // 设置表格的行数
    stand->ui->tableWidget->setRowCount(row);
    stand->ui->tableWidget->setColumnCount(column);
    // 设置表格的垂直表头的标签为字母
    stand->ui->tableWidget->setVerticalHeaderLabels(
                QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");
    for (int m = 0; m < row; m++) {
        for (int n = 0; n < column; n++) {
            // 创建一个新的单元格项目
            QTableWidgetItem *newItem = new QTableWidgetItem();
            // 把新的单元格项目添加到表格中
            stand->ui->tableWidget->setItem(m, n, newItem);
        }
    }
}

/*  渲染快速设置参比荧光 */
void ExperimentPlateUi::renderyingguangLine() {
    ui->yingguangLine->clear();
    // 定义两个列表，分别存储报告基因和淬火基因的名称
    QList<QString> reporterBox;
    QList<QString> quencherBox;

    // 遍历配置文件中的染料信息
    for (int l = 0; l < dyeFromConfig.length(); l++) {
        // 如果染料的类型是报告基因，就把它的名称添加到报告基因列表中
        if (dyeFromConfig[l]["type"] == "报告基因") {
            reporterBox.append(dyeFromConfig[l]["name"]);
            // 如果染料的类型是淬火基因，就把它的名称添加到淬火基因列表中
        } else if (dyeFromConfig[l]["type"] == "淬火基因") {
            quencherBox.append(dyeFromConfig[l]["name"]);
        }
    }

    // 遍历报告基因列表
    for (int l = 0; l < reporterBox.length(); l++) {
        // 把报告基因的名称添加到下拉列表中
        ui->yingguangLine->addItem(reporterBox[l]);
    }
    // 设置下拉列表的默认值为ROX
    ui->yingguangLine->setCurrentText("ROX");
}

/* 所有组件生效 */
void ExperimentPlateUi::allComponentsValid() {
    ui->sampleList->setEnabled(true);
    ui->targetList->setEnabled(true);

    ui->sample->setEnabled(true);
    ui->target->setEnabled(true);
    ui->allSelect->setEnabled(true);

    ui->clearTable->setEnabled(true);
    ui->materialType->setEnabled(true);

    ui->sampleTable->setEnabled(true);
}

/* 所有组件失效 */
void ExperimentPlateUi::allComponentsInvalid() {

    LOG << "fyb组件失效";

    ui->sampleList->setEnabled(false);
    ui->targetList->setEnabled(false);
    ui->allSelect->setEnabled(false);

    ui->sample->setEnabled(false);
    ui->target->setEnabled(false);

    ui->clearTable->setEnabled(false);
    ui->materialType->setEnabled(false);

    ui->sampleTable->setEnabled(false);
    LOG << "fyb组件失效<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<";
}

/* 样板表右键复制功能 */
void ExperimentPlateUi::slotActionCopy() {
    // 获取反应板的选择模型
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    // 获取选择的索引列表
    QModelIndexList indexList = selection->selectedIndexes();
    QModelIndex index = indexList[0];
    // 计算样本在反应板中的位置
    int count = index.row() + index.column() * 8;
    // 复制样本的名称、颜色和备注
    copyNameReporter.sampleName.name = reactionPlate.sampleList[count].name;
    copyNameReporter.sampleName.color_value = reactionPlate.sampleList[count].color_value;
    copyNameReporter.sampleName.remarks = reactionPlate.sampleList[count].remarks;
    // 遍历样本的目标报告基因
    for (int i = 0; i < 20; i++) {
        // 复制目标报告基因的信息，包括报告基因、名称、类型、淬火基因、数量、颜色和说明
        copyNameReporter.targetReporter[i].reporter = reactionPlate.targetList[count][i].reporter;
        copyNameReporter.targetReporter[i].name = reactionPlate.targetList[count][i].name;
        copyNameReporter.targetReporter[i].type = reactionPlate.targetList[count][i].type;
        copyNameReporter.targetReporter[i].quencher = reactionPlate.targetList[count][i].quencher;
        copyNameReporter.targetReporter[i].quantity = reactionPlate.targetList[count][i].quantity;
        copyNameReporter.targetReporter[i].color = reactionPlate.targetList[count][i].color;
        copyNameReporter.targetReporter[i].explain = reactionPlate.targetList[count][i].explain;
    }
}

/* 样板表右键粘贴功能 */
void ExperimentPlateUi::slotActionPaste() {
    // 获取反应板的选择的孔位
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    // 遍历孔位
    foreach(QModelIndex index, indexList) {
        // 设置样式
        widgetLabel = createLabelWidget();
        // 计算样本在反应板中的位置
        int count = index.row() + index.column() * 8;
        // 设置复制的样本的名称、颜色和备注
        reactionPlate.sampleList[count].name = copyNameReporter.sampleName.name;
        reactionPlate.sampleList[count].color_value = copyNameReporter.sampleName.color_value;
        reactionPlate.sampleList[count].remarks = copyNameReporter.sampleName.remarks;
        // 设置复制的样本的目标报告基因
        for (int i = 0; i < 4; i++) {
            reactionPlate.targetList[count][i].reporter = copyNameReporter.targetReporter[i].reporter;
            reactionPlate.targetList[count][i].name = copyNameReporter.targetReporter[i].name;
            reactionPlate.targetList[count][i].type = copyNameReporter.targetReporter[i].type;
            reactionPlate.targetList[count][i].quencher = copyNameReporter.targetReporter[i].quencher;
            reactionPlate.targetList[count][i].quantity = copyNameReporter.targetReporter[i].quantity;
            reactionPlate.targetList[count][i].color = copyNameReporter.targetReporter[i].color;
            reactionPlate.targetList[count][i].explain = copyNameReporter.targetReporter[i].explain;
        }

        // 反应板信息过滤
        if (copyNameReporter.sampleName.name != "null") {
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                QString name = copyNameReporter.sampleName.name;
                QLabel *label = createLabel(name);
                QColor color = stringToColor(copyNameReporter.sampleName.color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
                // label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
                vLayout->addWidget(label);
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == true &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == false) {
                QString name = reactionPlate.sampleList[count].name;
                if (name != "null") {
                    // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                    QLabel *label = createLabel(name);
                    // 将标签添加到垂直布局中
                    vLayout->addWidget(label);
                }
            }
            if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                    ui->tableFilter->menu()->actions().value(0)->isChecked() == false &&
                    ui->tableFilter->menu()->actions().value(2)->isChecked() == true) {
                QString name = reactionPlate.sampleList[count].name;
                if (name != "null") {
                    QLabel *label = new QLabel();
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);

                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    vLayout->addWidget(label);
                }
            }

        }

        int p = 0;
        for (int l = 0; l < 4; l++) {
            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                    ui->tableFilter->menu()->actions().value(1)->isChecked() == true) {
                if (copyNameReporter.targetReporter[l].reporter != "null") {
                    QString reporter = copyNameReporter.targetReporter[l].type;
                    if (reporter == "unknown(未知)") {
                        reporter = "U " + copyNameReporter.targetReporter[l].reporter;
                    }
                    if (reporter == "stander(标准)") {
                        reporter = "S " + copyNameReporter.targetReporter[l].reporter;
                    }
                    if (reporter == "NTC") { reporter = "N " + copyNameReporter.targetReporter[l].reporter; }
                    QLabel *label = createLabel(reporter);
                    QColor color = stringToColor(copyNameReporter.targetReporter[l].color);
                    QRgb rgbColor = qRgb(color.red(), color.green(), color.blue());
                    QString mRgbStr = QString::number(rgbColor, 16);
                    label->setStyleSheet("QLabel{border:2px solid #" + mRgbStr + ";}");
                    // label->setFixedSize(55, 20);
                    label->resize(static_cast<int>(strlen(reinterpret_cast<char *>(label->text().data()))) *
                                  label->font().pointSize(), 24);
                    label->setFixedHeight(22);
                    gLayout->addWidget(label, p / 10, p % 10);
                    p++;
                }
            }
        }
        // 设置布局和样式
        gLayout->setMargin(0);
        gLayout->setSpacing(0);
        vLayout->addLayout(gLayout);
        ui->sampleTable->setCellWidget(index.row(), index.column(), widgetLabel);
    }

    // 更新和渲染孔位信息表格
    renderDetailTable();
    markTable();
}

/* todo 样板表右键设置标准品功能 */
void ExperimentPlateUi::slotActionSetting() {
    // 创建两个列表，分别用于存储报告基因和淬火基因的名称
    QList<QString> reporterBox;
    QList<QString> quencherBox;

    // 清空standTargetName和standTargetReporter两个变量
    standTargetName.clear();
    standTargetReporter.clear();
    // 清空stand对象的ui属性中的表格控件的内容
    stand->ui->tableWidget->clear();
    // 设置表格控件的垂直表头标签为A到H
    stand->ui->tableWidget->setVerticalHeaderLabels(
                QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");


    // 遍历dyeFromConfig变量中的每个元素
    for (int l = 0; l < dyeFromConfig.length(); l++) {
        // 判断元素的type属性是否为"报告基因"
        if (dyeFromConfig[l]["type"] == "报告基因") {
            // 如果是，就将元素的name属性添加到reporterBox列表中
            reporterBox.append(dyeFromConfig[l]["name"]);
            // 判断元素的type属性是否为"淬火基因"
        } else if (dyeFromConfig[l]["type"] == "淬火基因") {
            // 如果是，就将元素的name属性添加到quencherBox列表中
            quencherBox.append(dyeFromConfig[l]["name"]);
        }
    }

    // 清空stand对象的ui属性中的目标下拉框的选项
    stand->ui->target->clear();
    // 遍历targetList中的每一行
    for (int i = 0; i < ui->targetList->rowCount(); i++) {
        // 将targetList中第i行第2列的文本添加到目标下拉框中
        stand->ui->target->addItem(ui->targetList->item(i, 2)->text());
    }

    // 获取材料类型下拉框的当前文本
    QString num = ui->materialType->currentText();
    // 调用renderStandTable函数，渲染stand对象的ui属性中的表格控件
    renderStandTable(num);

    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();

    int totalHoles = calculateTotalHoles();
    setChooseText(num, totalHoles);

    // 如果选择安排方式为“列”, 选择孔方式为“自动选择反应孔”
    if (stand->ui->radioBtn_1->isChecked() == true && stand->ui->radioBtn_3->isChecked() == true) {
        setStandLayout(row, column, true, true, false, false, false, false, false);
        stand->ui->textEdit->setText(str);
    }

    // 如果选择安排方式为“行”, 选择孔方式为“自动选择反应孔”
    if (stand->ui->radioBtn_2->isChecked() == true && stand->ui->radioBtn_3->isChecked() == true) {
        setStandLayout(row, column, false, true, false, false, false, false, false);
        stand->ui->textEdit->setText(str);
    }


    // 调用paintStand函数，绘制stand对象的图形
    paintStand();
    // 显示stand对象
    stand->show();
}

/* 样板表右键导出excel功能 */
void ExperimentPlateUi::slotActionExport() {
    // 弹出一个保存文件对话框，让用户选择保存的文件路径和格式
    QString filepath = QFileDialog::getSaveFileName(this, tr("Save as..."), QString(),
                                                    tr("EXCEL files (*.xls *.xlsx);;HTML-Files (*.txt);;"));

    // 判断用户是否选择了一个有效的路径
    if (!filepath.isEmpty()) {
        // 如果是，就创建一个文件对象，并以截断和写入模式打开
        QFile file(filepath);
        bool ret = file.open(QIODevice::Truncate | QIODevice::WriteOnly);
        // 如果打开失败，就返回
        if (!ret) { return; }

        // 创建一个文本流对象，关联到文件对象
        QTextStream stream(&file);
        // 定义一个字符串变量，用于存储详细表格中的内容
        QString conTents;
        // 获取详细表格的水平表头
        QHeaderView *header = ui->detailTable->horizontalHeader();
        // 如果表头存在，就遍历表头中的每一列
        if (header) {
            for (int i = 0; i < header->count(); i++) {
                // 获取表头中的第i列的项
                QTableWidgetItem *item = ui->detailTable->horizontalHeaderItem(i);
                // 如果项不存在，就跳过
                if (!item) { continue; }
                // 将项的文本添加到字符串变量中，并用空格分隔
                conTents += item->text() + " ";
            }
            conTents += "\n";
        }
        for (int i = 0; i < ui->detailTable->rowCount(); i++) {
            for (int j = 0; j < ui->detailTable->columnCount(); j++) {
                // 获取详细表格中第i行第j列的项
                QTableWidgetItem *item = ui->detailTable->item(i, j);
                if (!item) { continue; }
                // 获取项的文本
                QString str = item->text();
                // 将文本添加到字符串变量中，并用空格分隔
                conTents += str + " ";
            }
            conTents += "\n";
        }
        // 将字符串变量写入文本流中
        stream << conTents;
        // 关闭文件对象
        file.close();
    }
}

/* 快速设置添加样本点功能 */
void ExperimentPlateUi::slotSampleEdit() {
    // 最后一个样本名
    QString editName = ui->sample->itemText(ui->sample->count() - 1);

    // 如果样本名称不为空，执行以下操作
    if (editName == "") {
    } else {
        // 获取样本列表行数
        int samplerow = ui->sampleList->rowCount();
        // 将行数加一，为新项目腾出空间
        ui->sampleList->setRowCount(samplerow + 1);

        // 创建一个新的QTableWidgetItem，用于显示复选框
        QTableWidgetItem *check = new QTableWidgetItem();
        // 设置复选框的初始状态为未选中
        check->setCheckState(Qt::Unchecked);

        // 创建一个新的QTableWidgetItem，用于显示项目名称
        QString strname = editName;
        QTableWidgetItem *name = new QTableWidgetItem(strname);
        // c
        QColor qc = selectColor(flag[3], 1);
        // 创建一个新的QTableWidgetItem，用于显示颜色
        QString strcolor;
        QTableWidgetItem *color = new QTableWidgetItem(strcolor);
        // 设置颜色项的背景颜色为qc
        color->setBackgroundColor(qc);

        // 将三个QTableWidgetItem分别放在样本列表中对应的位置
        ui->sampleList->setItem(flag[3], 0, check);
        ui->sampleList->setItem(flag[3], 1, color);
        ui->sampleList->setItem(flag[3], 2, name);

        // 获取颜色项的指针
        QTableWidgetItem *item = ui->sampleList->item(flag[3], 1);
        // 禁止对颜色项进行编辑和选择
        item->setFlags(item->flags() & (~Qt::ItemIsEditable));
        item->setFlags(item->flags() & (~Qt::ItemIsSelectable));

        // 将flag[3]加一，为下一个项目准备
        flag[3]++;
    }


    // 获取样本列表中的最后一行的索引
    int in = ui->sampleList->rowCount() - 1;
    // 获取样本表中的选择模型
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    // 获取样本表中选中的单元格的索引列表
    QModelIndexList indexList = selection->selectedIndexes();
    // 定义一个变量a，用于记录是否有重复添加样本的情况
    int a = 0;
    // 遍历选中的单元格
    foreach(QModelIndex index, indexList) {
        widgetLabel = createLabelWidget();
        // 获取当前索引的行号
        int row = index.row();
        // 获取当前索引的列号
        int column = index.column();

        int count = 8 * column + row;
        //            if(reactionPlate.sampleList[count].name != "null"){
        //                if(a == 0){
        //                    QMessageBox::warning(this, "提示", "该孔位已经添加过样本");
        //                    a ++;
        //                }
        //            }
        //            else{

        // 判断样本列表中的第in行第2列的文本项是否为空或者文本内容为空
        if (ui->sampleList->item(in, 2) == nullptr || ui->sampleList->item(in, 2)->text().isEmpty()) {
            reactionPlate.sampleList[count].name = "null";
        } else {
            // 如果不是，就将反应板中的样本列表的第count个元素的名称设置为文本内容
            reactionPlate.sampleList[count].name = ui->sampleList->item(in, 2)->text();
        }

        if (ui->sampleList->item(in, 3) == nullptr || ui->sampleList->item(in, 3)->text().isEmpty()) {
            reactionPlate.sampleList[count].remarks = "null";
        } else {
            reactionPlate.sampleList[count].remarks = ui->sampleList->item(in, 3)->text();
        }

        // 获取样本列表中的第in行第1列的颜色项的背景色
        QColor col = ui->sampleList->item(in, 1)->backgroundColor();
        // 将背景色转换为字符串，并设置反应板中的样本列表的第count个元素的颜色值
        reactionPlate.sampleList[count].color_value = colorTostring(col);
        //            }
        // 判断tableFilter的菜单中的第0个和第2个动作是否都被选中，并且第0个动作的提示是否为"样本名称"
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                ui->tableFilter->menu()->actions().value(2)->isChecked()) {
            // 如果是，就获取反应板中的样本列表的第count个元素的名称
            QString name = reactionPlate.sampleList[count].name;


            // 判断名称是否不为"null"
            if (name != "null") {
                // 如果不是，就创建一个空字符串，并赋值给copySampleName数组的第count个元素
                copySampleName[count] = "";
                QLabel *label = createLabel(name);
                // 将反应板中的样本列表的第count个元素的颜色值转换为颜色对象
                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                vLayout->addWidget(label);
            }

        }
        // 判断tableFilter的菜单中的第0个和第2个动作的选中状态
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                !ui->tableFilter->menu()->actions().value(2)->isChecked()) {
            // 如果第0个动作的提示为"样本名称"，并且第0个动作被选中，而第2个动作没有被选中，就获取反应板中的样本列表的第count个元素的名称
            QString name = reactionPlate.sampleList[count].name;


            // 判断名称是否不为"null"
            if (name != "null") {
                // 如果不是，就创建一个空字符串，并赋值给copySampleName数组的第count个元素
                copySampleName[count] = "";
                // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                QLabel *label = createLabel(name);
                // 将标签添加到垂直布局中
                vLayout->addWidget(label);
            }
        }
        // 反应板信息过滤
        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                !ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                ui->tableFilter->menu()->actions().value(2)->isChecked()) {
            // 如果第0个动作的提示为"样本名称"，并且第0个动作没有被选中，而第2个动作被选中，就获取反应板中的样本列表的第count个元素的名称和颜色值
            QString name = reactionPlate.sampleList[count].name;

            // 判断名称是否不为"null"
            if (name != "null") {
                copySampleName[count] = "";
                QLabel *label = new QLabel();
                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                vLayout->addWidget(label);
            }
        }

        //  定义一个变量p，初始值为0
        int p = 0;
        // 用一个循环遍历反应板中的目标列表的第count个元素的前20个子元素
        for (int l = 0; l < 20; l++) {
            // 判断表格过滤器的菜单中的第1个动作是否被选中，并且提示是否为"靶基因"
            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                    ui->tableFilter->menu()->actions().value(1)->isChecked()) {

                // 如果是，就判断反应板中的目标列表的第count个元素的第l个子元素的reporter属性是否不为"null"
                if (reactionPlate.targetList[count][l].reporter != "null") {
                    createTargetLabel(reactionPlate, count, l, p, false);
                }
            }
        }

        // 将网格布局添加到垂直布局中
        gLayout->setMargin(0);
        gLayout->setSpacing(0);
        vLayout->addLayout(gLayout);
        // 将控件添加到样本表格中的第row行第column列的单元格中
        ui->sampleTable->setCellWidget(row, column, widgetLabel);

    }

    // 调用markTable函数，标记表格中的一些单元格
    markTable();
    // 调用renderDetailTable函数，渲染详细表格中的内容
    renderDetailTable();
}

/* 标准品界面点数设置 */
void ExperimentPlateUi::slotStandCountLine() {
    // 获取点数和复制品数，计算出总孔数
    //    int allCount = calculateTotalHoles();
    int count = stand->ui->countLine->text().toInt();
    int copy = stand->ui->copyLine->text().toInt();
    int allCount = count * copy;

    // 获取tableWidget的行数和列数
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();

    // 设置显示控件的文本为点数、复制品和孔位的关系
    stand->ui->showCount->setText(
                QString::number(count) + "点数 * " + QString::number(copy) + "复制品 = " + QString::number(allCount) +
                "个孔位");

    // 如果tableFlag为1，表示是管式，总孔位数不能超过32
    if (stand->tableFlag == 1 && allCount > 32) {
        allCount = 32;
    }
    // 如果tableFlag为0，表示是管式，总孔位数不能超过16
    if (stand->tableFlag == 0 && allCount > 16) {
        allCount = 16;
    }

    // 如果总孔位数小于等于0，设置为0
    if (allCount <= 0) {
        allCount = 0;
    }

    //如果选择孔方式为”自动选择反应孔”
    if (stand->ui->radioBtn_3->isChecked()) {
        // 获取耗材类型的当前文本（experimentplateui)
        QString num = ui->materialType->currentText();

        setChooseText(num, allCount);

        // 将总孔位数赋值给stand对象的属性
        stand->standCount = allCount;
        // 清空tableWidget的内容
        stand->ui->tableWidget->clear();

        // 设置表格控件的垂直表头为A到H
        stand->ui->tableWidget->setVerticalHeaderLabels(
                    QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");

        // 如果选择安排方式为“列”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是单重，执行以下操作
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "单重") {
            setStandLayout(row, column, true, true, true, true, false, true, false);

            // 将字符串设置为textEdit的内容，显示所有孔位的标签
            stand->ui->textEdit->setText(str);
        }
        // 如果选择安排方式为“行”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是单重，执行以下操作
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "单重") {
            setStandLayout(row, column, false, true, true, true, false, true, false);

            stand->ui->textEdit->setText(str);
        }

        // 如果选择安排方式为“列”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是多重，执行以下操作
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "多重") {
            setStandLayout(row, column, true, true, true, false, true, true, true);
            stand->ui->textEdit->setText(str);
        }
        // 如果选择安排方式为“行”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是多重，执行以下操作
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "多重") {
            setStandLayout(row, column, false, true, true, false, true, true, true);
            stand->ui->textEdit->setText(str);
        }
    }

    /* 标准品界面绘制标准曲线功能 */
    paintStand();
}

/* 标准品界面复制品设置 */
void ExperimentPlateUi::slotStandCopyLine() {
    // 获取点数和复制品数，计算出总孔数
    int count = stand->ui->countLine->text().toInt();
    int copy = stand->ui->copyLine->text().toInt();
    int allCount = count * copy;

    // 获取tableWidget的行数和列数
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();

    // 设置显示控件的文本为点数、复制品和孔位的关系
    stand->ui->showCount->setText(
                QString::number(count) + "点数 * " + QString::number(copy) + "复制品 = " + QString::number(allCount) +
                "个孔位");

    // 如果tableFlag为1，表示是管式，总孔位数不能超过32
    if (stand->tableFlag == 1 && allCount > 32) {
        allCount = 32;
    }
    // 如果tableFlag为0，表示是管式，总孔位数不能超过16
    if (stand->tableFlag == 0 && allCount > 16) {
        allCount = 16;
    }

    // 如果总孔位数小于等于0，设置为0
    if (allCount <= 0) {
        allCount = 0;
    }

    //如果选择孔方式为”自动选择反应孔”
    if (stand->ui->radioBtn_3->isChecked()) {
        // 获取耗材类型的当前文本（experimentplateui)
        QString num = ui->materialType->currentText();

        setChooseText(num, allCount);

        // 将总孔位数赋值给stand对象的属性
        stand->standCount = allCount;
        // 清空tableWidget的内容
        stand->ui->tableWidget->clear();

        // 设置表格控件的垂直表头为A到H
        stand->ui->tableWidget->setVerticalHeaderLabels(
                    QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");

        // 如果选择安排方式为“列”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是单重，执行以下操作
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "单重") {
            setStandLayout(row, column, true, true, true, true, false, true, false);
            // 将字符串设置为textEdit的内容，显示所有孔位的标签
            stand->ui->textEdit->setText(str);
        }

        // 如果选择安排方式为“行”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是单重，执行以下操作
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "单重") {
            setStandLayout(row, column, false, true, true, true, false, true, false);
            stand->ui->textEdit->setText(str);
        }

        // 如果选择安排方式为“列”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是多重，执行以下操作
        if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "多重") {
            setStandLayout(row, column, true, true, true, false, true, true, true);
            stand->ui->textEdit->setText(str);
        }
        // 如果选择安排方式为“行”, 选择孔方式为“自动选择反应孔”，并且模式控件的当前文本是多重，执行以下操作
        if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_3->isChecked() &&
                stand->ui->mode->currentText() == "多重") {
            setStandLayout(row, column, false, true, true, false, true, true, true);
            stand->ui->textEdit->setText(str);
        }


    }

    /* 标准品界面绘制标准曲线功能 */
    paintStand();
}

/* 标准品界面安排方式选择功能——列 */
void ExperimentPlateUi::slotStandRadioBtn1() {
    // 获取tableWidget的行数和列数
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();

    //如果选择孔方式为”自动选择反应孔”
    if (stand->ui->radioBtn_3->isChecked()) {
        // 清空tableWidget
        stand->ui->tableWidget->clear();
        // 设置tableWidget的垂直表头为A~H
        stand->ui->tableWidget->setVerticalHeaderLabels(
                    QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");

        //如果选择孔方式为”自动选择反应孔”，并且模式控件的当前文本是单重
        if (stand->ui->radioBtn_3->isChecked() && stand->ui->mode->currentText() == "单重") {
            setStandLayout(row, column, true, true, true, true, false, true, false);

            stand->ui->textEdit->setText(str);
        }

        //如果选择孔方式为”自动选择反应孔”，并且模式控件的当前文本是多重
        if (stand->ui->radioBtn_3->isChecked() && stand->ui->mode->currentText() == "多重") {
            setStandLayout(row, column, true, true, true, false, true, true, false);
            stand->ui->textEdit->setText(str);
        }

    }
}

/* 标准品界面安排方式选择功能——行 */
void ExperimentPlateUi::slotStandRadioBtn2() {
    // 获取tableWidget行数和列数
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();

    //如果选择孔方式为”自动选择反应孔”
    if (stand->ui->radioBtn_3->isChecked()) {
        // 清空tableWidget
        stand->ui->tableWidget->clear();
        // 设置tableWidget的垂直表头为A~H
        stand->ui->tableWidget->setVerticalHeaderLabels(
                    QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");
        //如果选择孔方式为”自动选择反应孔”，并且模式控件的当前文本是单重
        if (stand->ui->radioBtn_3->isChecked() && stand->ui->mode->currentText() == "单重") {

            setStandLayout(row, column, false, true, true, true, false, true, false);

            // 显示所有孔位的标签
            stand->ui->textEdit->setText(str);
        }

        //如果选择孔方式为”自动选择反应孔”，并且模式控件的当前文本是多重
        if (stand->ui->radioBtn_3->isChecked() && stand->ui->mode->currentText() == "多重") {
            setStandLayout(row, column, false, true, true, false, true, true, false);
            stand->ui->textEdit->setText(str);
        }
    }
}

/* 标准品界面孔方式选择功能——自动选择 */
void ExperimentPlateUi::slotStandRadioBtn3() {
    // 清空反应板右键标准品设置存储反应板名称和信息
    standTargetName.clear();
    standTargetReporter.clear();

    // 清空tableWidget的内容
    stand->ui->tableWidget->clear();
    // 设置tableWidget的垂直表头为A到H
    stand->ui->tableWidget->setVerticalHeaderLabels(
                QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");


    // 获取tableWidget的行数和列数
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();

    // 遍历 “为标准曲线选择靶基因” 所有选项， 设置他们的前景色为黑色
    for (int l = 0; l < stand->ui->target->count(); l++) {
        stand->ui->target->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    }

    // 获取耗材类型的当前文本（experimentPlateUi)
    QString num = ui->materialType->currentText();

    int totalHoles = calculateTotalHoles();
    setChooseText(num, totalHoles);

    // 如果选择安排方式为“列”，按照从左到右，从上到下的顺序生成和显示孔位的标签
    if (stand->ui->radioBtn_1->isChecked()) {
        setStandLayout(row, column, true, true, false, false, false, false, false);

        // 显示所有孔位的标签
        stand->ui->textEdit->setText(str);
    }

    // 如果选择安排方式为“行”，按照从上到下，从左到右的顺序生成和显示孔位的标签
    if (stand->ui->radioBtn_2->isChecked()) {
        setStandLayout(row, column, false, true, false, false, false, false, false);

        stand->ui->textEdit->setText(str);
    }
}

/* 标准品界面孔方式选择功能——手动选择 */
void ExperimentPlateUi::slotStandRadioBtn4() {
    // 清空反应板右键标准品设置存储反应板名称和信息
    standTargetName.clear();
    standTargetReporter.clear();

    // 清空tableWidget的内容
    stand->ui->tableWidget->clear();
    // 设置tableWidget的垂直表头为A到H
    stand->ui->tableWidget->setVerticalHeaderLabels(
                QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");

    // 获取材料类型的当前文本
    QString num = ui->materialType->currentText();
    setChooseText(num, 0);
    // 遍历目标控件的所有项，设置它们的前景色为黑色
    for (int l = 0; l < stand->ui->target->count(); l++) {
        stand->ui->target->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    }
    // 清空textEdit
    stand->ui->textEdit->clear();
}

/* 标准品界面已选孔位信息显示功能 */
void ExperimentPlateUi::slotStandShowInfo() {
    if (stand->ui->radioBtn_4->isChecked()) {
        QString text = "";
        // 获取表格的选择模型
        QItemSelectionModel *selection = stand->ui->tableWidget->selectionModel();
        // 获取选择模型中选中的索引列表
        QModelIndexList indexList = selection->selectedIndexes();
        // 遍历索引列表，根据行号和列号生成位置标签，并拼接到字符串中
        foreach(QModelIndex index, indexList) {
            QString label = rowLetters[index.row()];
            QString number = QString::number(index.column() + 1);
            text += label + number + " ";
        }
        // 将字符串显示在文本框中
        stand->ui->textEdit->setText(text);
    }
}

/* 标准品界面重置功能 */
void ExperimentPlateUi::slotStandNew() {
    // 获取表格的行数和列数
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();


    // 遍历目标列表，将每个项目的前景色设置为黑色
    for (int l = 0; l < stand->ui->target->count(); l++) {
        stand->ui->target->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    }
    // 清空
    standTargetName.clear();
    standTargetReporter.clear();

    // 设置复制行、计数行和起始行的文本为默认值
    stand->ui->copyLine->setText("3");
    stand->ui->countLine->setText("5");
    stand->ui->startLine->setText("1.0");
    // 获取材料类型的文本
    QString num = ui->materialType->currentText();

    int totalHoles = calculateTotalHoles();
    setChooseText(num, totalHoles);
    // 设置单选按钮的状态为默认值
    stand->ui->radioBtn_1->setChecked(true);
    stand->ui->radioBtn_3->setChecked(true);
    setStandLayout(row, column, true, true, false, false, false, false, false);
    // 将字符串显示在文本框中
    stand->ui->textEdit->setText(str);
    // 清空表格中的内容
    stand->ui->tableWidget->clear();
    // 设置表格的垂直表头标签为字母A到H
    stand->ui->tableWidget->setVerticalHeaderLabels(
                QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H");
    // 调用paintStand()函数，绘制实验板的图形
    paintStand();
}

/* 标准品界面确认功能 */
void ExperimentPlateUi::slotStandConfirm() {
    // 获取标准板的行数和列数
    int row = stand->ui->tableWidget->rowCount();
    int column = stand->ui->tableWidget->columnCount();


    // 初始化标准板的选中状态为0
    for (int i = 0; i < 96; i++) {
        standIndex[i] = 0;
    }
    // 获取用户输入的数量和复制数
    int count = stand->ui->countLine->text().toInt();
    int copy = stand->ui->copyLine->text().toInt();
    // 计算总的选中数
    int allCount = count * copy;

    // 如果标准板是32孔，且总的选中数大于32，设置总的选中数为32
    if (stand->tableFlag == 1 && allCount > 32) {
        allCount = 32;
    }
    // 如果标准板是16孔，且总的选中数大于16，设置总的选中数为16
    if (stand->tableFlag == 0 && allCount > 16) {
        allCount = 16;
    }

    // 如果总的选中数小于等于0，设置总的选中数为0
    if (allCount <= 0) {
        allCount = 0;
    }

    // 如果选择安排方式为“列”, 选择孔方式为“自动选择反应孔”
    if (stand->ui->radioBtn_1->isChecked() && stand->ui->radioBtn_3->isChecked()) {
        fillStandIndex(standIndex, row, column, true);
    }
    // 如果选择安排方式为“行”, 选择孔方式为“自动选择反应孔”
    if (stand->ui->radioBtn_2->isChecked() && stand->ui->radioBtn_3->isChecked()) {
        fillStandIndex(standIndex, row, column, false);
    }
    // 如果用户选择了自定义的方式
    if (stand->ui->radioBtn_4->isChecked()) {
        // 获取用户在标准板上选择的单元格
        QItemSelectionModel *selection = stand->ui->tableWidget->selectionModel();
        QModelIndexList indexList = selection->selectedIndexes();
        foreach(QModelIndex index, indexList) {
            // 设置标准板的选中状态为1
            standIndex[index.row() + index.column() * 8] = 1;
        }
    }

    // 清空反应板信息
    clearPlateInformation();

    // 获取用户选择的材料类型
    QString consume = ui->materialType->currentText();
    // 从XML文件中读取并渲染表格的行数和列数
    readAndRenderTableRowColumnFromXML(consume);

    if (consume == "芯片-16" || consume == "管式") {
        for (int m = 0; m < row; m++) {
            for (int n = 0; n < column; n++) {
                // 计算表格位置对应的实验板位置
                int ccount = m + n * 8;
                if (standIndex[ccount] == 1) {
                    handlerStandPlate(count, ccount);
                }
            }
        }
    }

    // 重新给反应板上的color赋值
    for (auto &i: reactionPlate.targetList) {
        for (auto &j: i) {
            if (j.reporter != "null") {
                // 匹配靶基因列表的颜色
                for (int l = 0; l < ui->targetList->rowCount(); l++) {
                    if (j.reporter == getComboBoxFromTable(ui->targetList, l, 3)->currentText()) {
                        j.color = colorTostring(ui->targetList->item(l, 1)->backgroundColor());
                    }
                }
            }
        }
    }

    for (int i = 0; i < 96; i++) {
        widgetLabel = createLabelWidget();
        int p = 0;
        // 遍历反应板上的目标列表
        for (int l = 0; l < 20; l++) {
            // 如果用户选择了靶基因的过滤条件，并且过滤条件是选中状态
            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                    ui->tableFilter->menu()->actions().value(1)->isChecked()) {
                // 如果反应板上的目标报告者不为空
                if (reactionPlate.targetList[i][l].reporter != "null") {
                    createTargetLabel(reactionPlate, i, l, p, false);
                }
            }
        }
        gLayout->setMargin(0);
        gLayout->setSpacing(0);
        vLayout->addLayout(gLayout);
        ui->sampleTable->setCellWidget(i % 8, i / 8, widgetLabel);
    }
    stand->hide();

    markTable();
    renderDetailTable();
}

/* 更新靶基因和样本并渲染 */
void ExperimentPlateUi::slotUpdateTable(int) {
    //    int flag = 0;
    //    for(int i = ui->targetList->rowCount() - 1; i > 0; i ++){
    //        QWidget *widget_reporter = ui->targetList->cellWidget(i, 3);
    //        QComboBox *combo_reporter = (QComboBox*)widget_reporter;
    //        QString string_reporter = combo_reporter->currentText();
    //        for(int j = i - 1; j >= 0; j ++){
    //            QWidget *widget_reporter1 = ui->targetList->cellWidget(j, 3);
    //            QComboBox *combo_reporter1 = (QComboBox*)widget_reporter1;
    //            QString string_reporter1 = combo_reporter1->currentText();

    //            if(string_reporter1 == string_reporter){
    //                flag = 1;
    //                break;
    //            }
    //        }
    //        if(flag == 1){

    //            break;
    //        }
    //    }
    updateTargetListInfo();
    targetInfoRenderTargetList();
    updateTable();

}

/* 记录三种基因类型的数量和孔位数量 */
void ExperimentPlateUi::copystartCountChanged(int value) {
    // 获取样本表格的选择模型
    QItemSelectionModel *startSelection = ui->sampleTable->selectionModel();
    // 获取选择的索引列表
    QModelIndexList startIndexList = startSelection->selectedIndexes();

    int flag = 0;
    // 计算样本在反应板中的位置
    foreach(QModelIndex index, startIndexList) {
        int count = index.column() * 8 + index.row();

        // 如果不是第一个索引
        if (flag != 0) {
            // 清空样本的名称
            reactionPlate.sampleList[count].name = "null";
        }
        // 清空复制样本的名称
        copySampleName[count] = "";
        flag++;
    }
    updateTable();


    int tableCount;

    // 获取用户界面上的复制数量
    int copyNum = ui->copyCount->value();
    // 获取用户界面上的起始位置
    int startNum = ui->startCount->value();
    // 获取用户界面上的材料类型的索引
    int index = ui->materialType->currentIndex();
    int count, allCount;
    // 如果耗材类型索引是0
    if (index == 0) {
        // 设置每行的数量为2，总数量为16
        count = 2;
        allCount = 16;
    }
    // 如果耗材类型索引是1
    if (index == 1) {
        // 设置每行的数量为4，总数量为32
        count = 4;
        allCount = 32;
    }

    // 获取样本表的选择模型
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    // 获取选择的索引列表
    QModelIndexList indexList = selection->selectedIndexes();
    // 如果索引列表不为空
    if (indexList.length() > 0) {
        // 获取第一个索引
        QModelIndex chooseIndex = indexList[0];
        // 获取索引的列和行
        int chooseColumn = chooseIndex.column();
        int chooseRow = chooseIndex.row();
        // 计算样本在反应板中的位置
        tableCount = chooseColumn * 8 + chooseRow;

        // 如果样本的名称是null，表示没有选择样本类型
        if (reactionPlate.sampleList[tableCount].name == "null") {
            cusMsg->show(this, CMsg::CWarning, "提示", "请先输入样本名称或靶基因信息");
            // 如果样本的名称不是null，表示已经选择了样本类型
        } else if (reactionPlate.sampleList[tableCount].name != "null") {
            // 定义一个变量，用于记录渲染的单元格数量
            int renderItemCount = 0;
            // 如果用户界面上选择了水平方向
            if (ui->chooseShuiping->isChecked()) {
                // 计算选择的样本在反应板中的位置
                int selectCount = count * chooseRow + chooseColumn;
                // 定义一个变量，用于记录循环次数
                int xunhuan = 0;
                // 当选择的位置小于总数量，并且循环次数小于2时，继续循环
                while (selectCount < allCount && xunhuan < 2) {
                    // 遍历复制数量
                    for (int k = 0; k < copyNum; k++) {
                        // 计算选择的样本在表格中的行和列
                        int selectRow = selectCount / count;
                        int selectColumn = selectCount % count;


                        // 当选择的位置小于总数量时，继续循环
                        while (selectCount < allCount) {
                            // 计算选择的样本在表格中的行和列
                            selectRow = selectCount / count;
                            selectColumn = selectCount % count;
                            // 创建一个新的单元格项目
                            QTableWidgetItem *newItem = new QTableWidgetItem();
                            // 把新的单元格项目添加到表格中
                            ui->sampleTable->setItem(selectRow, selectColumn, newItem);
                            // 获取表格中的单元格项目
                            QTableWidgetItem *item = ui->sampleTable->item(selectRow, selectColumn);
                            // 如果单元格项目没有被选中，就增加选择的位置
                            if (!item->isSelected()) {
                                selectCount++;
                            } else { break; }
                        }
                        if (selectCount >= allCount) { break; }
                        // 计算渲染的样本在反应板中的位置
                        int renderCount = selectColumn * 8 + selectRow;

                        // 复制样本的名称、颜色和备注
                        reactionPlate.sampleList[renderCount].name = reactionPlate.sampleList[tableCount].name;
                        reactionPlate.sampleList[renderCount].color_value = reactionPlate.sampleList[tableCount].color_value;
                        reactionPlate.sampleList[renderCount].remarks = reactionPlate.sampleList[tableCount].remarks;
                        widgetLabel = createLabelWidget();
                        // 如果用户界面上选择了显示样本名称和起始位置
                        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                                ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                                ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                            // 拼接样本的名称和起始位置
                            QString name = reactionPlate.sampleList[renderCount].name + "-" + QString::number(startNum);
                            // 复制样本的名称
                            copySampleName[renderCount] = name;
                            QLabel *label = createLabel(name);
                            // 把字符串转换为颜色对象
                            QColor color = stringToColor(reactionPlate.sampleList[renderCount].color_value);
                            QString mRgbStr = QString::number(color.rgb(), 16);
                            widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                            vLayout->addWidget(label);
                        }
                        // 如果用户界面上选择了显示样本名称，但没有选择显示起始位置
                        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                                ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                                !ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                            QString name = reactionPlate.sampleList[renderCount].name + "-" + QString::number(startNum);
                            copySampleName[renderCount] = name;
                            if (name != "null") {
                                // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                                QLabel *label = createLabel(name);
                                // 将标签添加到垂直布局中
                                vLayout->addWidget(label);
                            }
                        }
                        // 如果用户界面上选择了显示起始位置，但没有选择显示样本名称
                        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                                !ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                                ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                            QString name = reactionPlate.sampleList[renderCount].name + "-" + QString::number(startNum);
                            copySampleName[renderCount] = name;
                            if (name != "null") {
                                QLabel *label = new QLabel();
                                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                                QString mRgbStr = QString::number(color.rgb(), 16);
                                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                                vLayout->addWidget(label);
                            }
                        }

                        // 定义一个变量，用于记录靶基因的数量
                        int p = 0;
                        // 遍历样本的靶基因
                        for (int l = 0; l < 20; l++) {
                            // 如果用户界面上选择了显示靶基因
                            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                                    ui->tableFilter->menu()->actions().value(1)->isChecked()) {
                                // 如果靶基因的报告基因不是null，表示有选择靶基因
                                if (reactionPlate.targetList[renderCount][l].reporter != "null") {
                                    createTargetLabel(reactionPlate, renderCount, l, p, false);
                                }
                            }
                        }
                        // 设置网格布局的边距和间距为0
                        gLayout->setMargin(0);
                        gLayout->setSpacing(0);
                        // 把网格布局添加到垂直布局中
                        vLayout->addLayout(gLayout);
                        // 把标签容器添加到表格中的单元格项目中
                        ui->sampleTable->setCellWidget(selectRow, selectColumn, widgetLabel);
                        // 增加渲染的数量
                        renderItemCount++;
                        // 如果渲染的数量大于或等于复制数量的两倍，就跳出循环
                        if (renderItemCount >= 2 * copyNum) { break; }
                        // 增加选择的位置
                        selectCount++;
                        // 如果选择的位置大于或等于总数量，就跳出循环
                        if (selectCount >= allCount) { break; }
                    }
                    // 增加起始位置
                    startNum++;
                    // 增加循环次数
                    xunhuan++;
                }
            } else if (ui->chooseChuizhi->isChecked()) {
                int selectCount = 8 * chooseColumn + chooseRow;
                // 定义一个变量，用于记录循环次数
                int xunhuan = 0;
                // 当选择的位置小于总数量，并且循环次数小于2时，继续循环
                while (selectCount < allCount && xunhuan < 2) {
                    for (int k = 0; k < copyNum; k++) {
                        // 计算选择的样本在表格中的行和列
                        int selectRow = selectCount % 8;
                        int selectColumn = selectCount / 8;

                        // 当选择的位置小于总数量时，继续循环
                        while (selectCount < allCount) {
                            // 计算选择的样本在表格中的行和列
                            selectColumn = selectCount / 8;
                            selectRow = selectCount % 8;
                            // 创建一个新的单元格项目
                            QTableWidgetItem *newItem = new QTableWidgetItem();
                            // 把新的单元格项目添加到表格中
                            ui->sampleTable->setItem(selectRow, selectColumn, newItem);
                            // 获取表格中的单元格项目
                            QTableWidgetItem *item = ui->sampleTable->item(selectRow, selectColumn);
                            // 如果单元格项目没有被选中，就增加选择的位置
                            if (!item->isSelected()) {
                                selectCount++;
                            } else { break; }
                        }
                        // 如果选择的位置大于或等于总数量，就跳出循环
                        if (selectCount >= allCount) { break; }

                        // 计算渲染的样本在反应板中的位置
                        int renderCount = selectColumn * 8 + selectRow;
                        // 复制样本的名称、颜色和备注
                        reactionPlate.sampleList[renderCount].name = reactionPlate.sampleList[tableCount].name;
                        reactionPlate.sampleList[renderCount].color_value = reactionPlate.sampleList[tableCount].color_value;
                        reactionPlate.sampleList[renderCount].remarks = reactionPlate.sampleList[tableCount].remarks;
                        widgetLabel = createLabelWidget();
                        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                                ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                                ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                            QString name = reactionPlate.sampleList[renderCount].name + "-" + QString::number(startNum);
                            copySampleName[renderCount] = name;
                            QLabel *label = createLabel(name);
                            QColor color = stringToColor(reactionPlate.sampleList[renderCount].color_value);
                            QString mRgbStr = QString::number(color.rgb(), 16);
                            widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                            vLayout->addWidget(label);
                        }
                        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                                ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                                !ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                            QString name = reactionPlate.sampleList[renderCount].name + "-" + QString::number(startNum);
                            copySampleName[renderCount] = name;
                            if (name != "null") {
                                // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                                QLabel *label = createLabel(name);
                                // 将标签添加到垂直布局中
                                vLayout->addWidget(label);
                            }
                        }
                        if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                                !ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                                ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                            QString name = reactionPlate.sampleList[renderCount].name + "-" + QString::number(startNum);
                            copySampleName[renderCount] = name;
                            if (name != "null") {
                                QLabel *label = new QLabel();
                                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                                QString mRgbStr = QString::number(color.rgb(), 16);
                                widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                                vLayout->addWidget(label);
                            }
                        }

                        // 定义一个变量，用于记录靶基因的数量
                        int p = 0;
                        // 遍历样本的靶基因
                        for (int l = 0; l < 20; l++) {
                            // 如果用户界面上选择了显示靶基因
                            if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                                    ui->tableFilter->menu()->actions().value(1)->isChecked()) {
                                // 如果靶基因的报告基因不是null，表示有选择靶基因
                                if (reactionPlate.targetList[renderCount][l].reporter != "null") {
                                    createTargetLabel(reactionPlate, renderCount, l, p, false);
                                }
                            }
                        }
                        // 设置网格布局的边距和间距为0
                        gLayout->setMargin(0);
                        gLayout->setSpacing(0);
                        // 把网格布局添加到垂直布局中
                        vLayout->addLayout(gLayout);
                        // 把标签容器添加到表格中的单元格项目中
                        ui->sampleTable->setCellWidget(selectRow, selectColumn, widgetLabel);
                        // 增加选择的位置
                        selectCount++;
                        // 如果选择的位置大于或等于总数量，就跳出循环
                        if (selectCount >= allCount) { break; }
                    }
                    // 增加起始位置
                    startNum++;
                    // 增加循环次数
                    xunhuan++;
                }
            }
        }
    }
    markTable();
}

/* 高级设置：更新靶基因面板内容 */
void ExperimentPlateUi::updateTargetListInfo() {
    /* 记录靶基因当前索引 */
    int index = 0;
    /* 遍历靶基因面板所有行 */
    for (int i = 0; i < ui->targetList->rowCount(); i++) {
        /* 判断第三列是否有文本 */
        if (ui->targetList->item(i, 2) == nullptr || ui->targetList->item(i, 2)->text().isEmpty()) {
            targetListInfo[index][1] = "";
        } else {
            targetListInfo[index][1] = ui->targetList->item(i, 2)->text();
        }

        /* 获取第四列的单元格中的下拉框控件 */
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, i, 3);
        /* 获取下拉框控件当前选中的文本 */
        QString string_reporter = combo_reporter->currentText();
        targetListInfo[index][2] = string_reporter;

        /* 获取第五列的单元格中的下拉框控件 */
        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, i, 4);
        QString string_quencher = combo_quencher->currentText();
        targetListInfo[index][3] = string_quencher;

        /* 获取第六列的单元格中的下拉框控件 */
        QComboBox *combo_type = getComboBoxFromTable(ui->targetList, i, 5);
        QString string_type = combo_type->currentText();
        targetListInfo[index][4] = string_type;

        /* 判断第七列是否有文本 */
        if (ui->targetList->item(i, 6) == nullptr || ui->targetList->item(i, 6)->text().isEmpty()) {
            targetListInfo[index][5] = "";
        } else {
            targetListInfo[index][5] = ui->targetList->item(i, 6)->text();
        }

        if (ui->targetList->item(i, 7) == nullptr || ui->targetList->item(i, 7)->text().isEmpty()) {
            targetListInfo[index][6] = "";
        } else {
            targetListInfo[index][6] = ui->targetList->item(i, 7)->text();
        }

        /* 获取第二列的颜色对象 */
        // 如果报告基因为下述几个基因，则设置为固定颜色
        /* 当报告基因为FAM 或SYBR 或Green时为蓝色 */
        if(string_reporter == "FAM"
                || string_reporter == "SYBR"
                || string_reporter == "Green"){
            targetListInfo[index][0] = colorTostring(selectColor(0, 2));

        }
        /* 当报告基因为CY5 或LIZ时为红色 */
        else if(string_reporter == "CY5"
                 || string_reporter == "LIZ"){
            targetListInfo[index][0] = colorTostring(selectColor(1, 2));

        }
        /* 当报告基因为VIC或HEX或TET或JOE时为绿色 */
        else if(string_reporter == "VIC"
                 || string_reporter == "HEX"
                 || string_reporter == "JOE"
                 || string_reporter == "TET"){
            targetListInfo[index][0] = colorTostring(selectColor(2, 2));
        }
        /* 当报告基因为ROX或TexasRed时为黄色 */
        else if(string_reporter == "ROX"
                 || string_reporter == "TexasRed"){
            targetListInfo[index][0] = colorTostring(selectColor(3, 2));
        }
        /* 当不为上述颜色时，则将当前行和颜色数组取余，获得当前行所对应的数组中的的颜色 */
        else {
            int curColorMap2ColorArray = i % 13; // 当前行所对应的数组颜色
            targetListInfo[index][0] = colorTostring(selectColor(curColorMap2ColorArray, 2));
        }

        index++;
    }
}

/* 将靶基因面板中的内容渲染成成列表 */
void ExperimentPlateUi::targetInfoRenderTargetList() {
    /* 将每行的各项的值设置给靶基因列表的对应单元格 */
    for (int row = 0; row < ui->targetList->rowCount(); row++) {
        /*  获取颜色项的字符串 */
        QString strcolor = targetListInfo[row][0];
        QColor color = stringToColor(strcolor);
        /* 设置靶基因列表中对应单元格的背景颜色 */
        ui->targetList->item(row, 1)->setBackgroundColor(color);

        /* 获取名称项的字符串 */
        QString strname = targetListInfo[row][1];
        /* 设置靶基因列表中对应单元格的文本 */
        ui->targetList->item(row, 2)->setText(strname);

        /* 获取报告基因的字符串 */
        QString string_reporter = targetListInfo[row][2];

        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, row, 3);
        /* 设置下拉框控件当前选中的文本 */
        combo_reporter->setCurrentText(string_reporter);

        /* 获取淬灭基因项的字符串 */
        QString string_quencher = targetListInfo[row][3];
        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, row, 4);
        combo_quencher->setCurrentText(string_quencher);

        /* 获取靶基因类型项的字符串 */
        QString string_type = targetListInfo[row][4];
        /* 获取靶基因类型下拉框控件 */
        QComboBox *combo_type = getComboBoxFromTable(ui->targetList, row, 5);
        combo_type->setCurrentText(string_type);

        QTableWidgetItem *item = ui->targetList->item(row, 6);
        /* 设置靶基因数量为 1 */
        if (string_type.contains("and") && targetListInfo[row][5] == "") {
            //            LOG << "1.0在这";
            item->setText("1.0");

            item->setFlags(item->flags() | Qt::ItemIsEditable);
        } else if (string_type.contains("and") && targetListInfo[row][5] != "") {
            item->setText(targetListInfo[row][5]);
            /* 设置单元格为可编辑 */
            item->setFlags(item->flags() | Qt::ItemIsEditable);
        } else {
            /* 设置单元格的文本为空 */
            item->setText("");
            /* 设置单元格为不可编辑 */
            item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        }

        QString string_mark = targetListInfo[row][6];
        ui->targetList->item(row, 7)->setText(string_mark);
    }

    for (int i = 0; i < 96; i++) {
        for (int j = 0; j < 20; j++) {
            if (reactionPlate.targetList[i][j].name != "null") {
                for (int l = 0; l < ui->targetList->rowCount(); l++) {
                    if (reactionPlate.targetList[i][j].name == ui->targetList->item(l, 2)->text()) {
                        /* 获取表格中第1列的单元格的背景颜色 */
                        QColor color = ui->targetList->item(l, 1)->backgroundColor();
                        /* 将颜色转换成字符串 */
                        reactionPlate.targetList[i][j].color = colorTostring(color);

                        if (ui->targetList->item(l, 2) == nullptr || ui->targetList->item(l, 2)->text().isEmpty()) {
                            reactionPlate.targetList[i][j].name = "";
                        } else {
                            reactionPlate.targetList[i][j].name = ui->targetList->item(l, 2)->text();
                        }
                        /* 获取报告基因单元格中的下拉框控件 */
                        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
                        QString string_reporter = combo_reporter->currentText();
                        reactionPlate.targetList[i][j].reporter = string_reporter;

                        /* 获取淬灭基因单元格中的下拉框控件 */
                        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, l, 4);
                        QString string_quencher = combo_quencher->currentText();
                        reactionPlate.targetList[i][j].quencher = string_quencher;

                        /* 获取靶基因类型单元格中的下拉框控件 */
                        QComboBox *combo_type = getComboBoxFromTable(ui->targetList, l, 5);
                        QString string_type = combo_type->currentText();
                        reactionPlate.targetList[i][j].type = string_type;

                        if (ui->targetList->item(l, 6) == nullptr || ui->targetList->item(l, 6)->text().isEmpty()) {
                            reactionPlate.targetList[i][j].quantity = "";
                        } else {
                            reactionPlate.targetList[i][j].quantity = ui->targetList->item(l, 6)->text();
                        }

                        if (ui->targetList->item(l, 7) == nullptr || ui->targetList->item(l, 7)->text().isEmpty()) {
                            reactionPlate.targetList[i][j].explain = "";
                        } else {
                            reactionPlate.targetList[i][j].explain = ui->targetList->item(l, 7)->text();
                        }

                        break;
                    }
                }
            }
        }
    }
    markTable();
}

/* 高级设置：更新样本面板内容 */
void ExperimentPlateUi::updateSampleListInfo() {
    // 初始化索引
    int index = 0;
    for (int i = 0; i < ui->sampleList->rowCount(); i++) {
        // 如果第三列为空或者没有文本
        if (ui->sampleList->item(i, 2) == nullptr || ui->sampleList->item(i, 2)->text().isEmpty()) {
            // 清空样本列表信息中的名称
            sampleListInfo[index][0] = "";
        } else {
            // 否则获取第三列的文本作为样本列表信息中的名称
            sampleListInfo[index][0] = ui->sampleList->item(i, 2)->text();
        }
        // 如果第四列为空或者没有文本
        if (ui->sampleList->item(i, 3) == nullptr || ui->sampleList->item(i, 2)->text().isEmpty()) {
            sampleListInfo[index][1] = "";
        } else {
            sampleListInfo[index][1] = ui->sampleList->item(i, 3)->text();
        }
        index++;
    }
}

/* 将样本面板中的内容渲染成成列表 */
void ExperimentPlateUi::sampleInfoRenderSampleList() {
    for (int row = 0; row < ui->sampleList->rowCount(); row++) {
        /* 获取样本数组中对应的name值 */
        QString string_name = sampleListInfo[row][0];
        /* 将name值赋值给样本表中对应的单元格 */
        ui->sampleList->item(row, 1)->setText(string_name);

        /* 获取样本数组中对应的mark值 */
        QString string_mark = sampleListInfo[row][1];
        /* 将mark值赋值给样本表中对应的单元格 */
        ui->sampleList->item(row, 2)->setText(string_mark);
    }


}

/* 反应版双击弹窗设置样本类型 */
void ExperimentPlateUi::doubleClickTypeChanged(int) {
    LOG << "反应板双击弹窗设置样本类型";
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    int count;
    foreach(QModelIndex index, indexList) {
        int row = index.row();
        int column = index.column();
        count = column * 8 + row;
        int in = view->ui->targetComboBox->currentIndex();
        int k = 0;
        if (view->ui->typeComboBox->currentText().contains("and")) {
            view->ui->countLineEdit->setEnabled(true);
            for (k = 0; k < 20; k++) {
                if (reactionPlate.targetList[count][k].name == view->ui->targetComboBox->currentText()) {
                    in = view->ui->targetComboBox->currentIndex();
                    if (reactionPlate.targetList[count][k].quantity != "null" &&
                            reactionPlate.targetList[count][k].quantity != "") {
                        view->ui->countLineEdit->setText(reactionPlate.targetList[count][k].quantity);
                    } else {
                        view->ui->countLineEdit->setText("1.0");
                    }
                    break;
                }
            }
        } else {
            view->ui->countLineEdit->setEnabled(false);
            view->ui->countLineEdit->setText("");
        }
        for (k = 0; k < 20; k++) {
            // 在反应版找到孔位的靶基因名称与view的靶基因名称相同,就将反应板此靶基因的样本类型和数量替换掉
            if (reactionPlate.targetList[count][k].name == view->ui->targetComboBox->currentText()) {
                reactionPlate.targetList[count][k].type = view->ui->typeComboBox->currentText();
                if (view->ui->countLineEdit->text() != "") {
                    reactionPlate.targetList[count][k].quantity = view->ui->countLineEdit->text();
                } else {
                    reactionPlate.targetList[count][k].quantity = "";
                }
                // 重新设置方框靶基因信息
                QString reporter = reactionPlate.targetList[count][k].type;
                if (reporter == "unknown(未知)") { reporter = "U " + reactionPlate.targetList[count][k].reporter; }
                // 如果类型是"stander(标准)"，则在报告基因前加上"S "
                if (reporter == "stander(标准)") { reporter = "S " + reactionPlate.targetList[count][k].reporter; }
                // 如果类型是"NTC"，则在报告基因前加上"N "
                if (reporter == "NTC") { reporter = "N " + reactionPlate.targetList[count][k].reporter; }
                LOG << " 重新设置方框靶基因信息: " << reporter;
                labelPtr->setText(reporter);
                LOG << "labelPtr->text(): " << labelPtr->text();
                break;
            }
        }
        // 上面语句替换下面语句
        //        targetListInfo[in][4] = view->ui->typeComboBox->currentText();
        //        reactionPlate.targetList[count][in].type = view->ui->typeComboBox->currentText();
        //        if (view->ui->countLineEdit->text() != "") {
        //            targetListInfo[in][5] = view->ui->countLineEdit->text();
        //            reactionPlate.targetList[count][k].quantity = view->ui->countLineEdit->text();
        //        } else {
        //            targetListInfo[in][5] = "";
        //        }

    }
    // 修改数据后不更新靶基因列表
    //    targetInfoRenderTargetList();
    markTable();
    updateTable();
}

/* 双击反应板孔位设置信息 */
void ExperimentPlateUi::doubleClickCountChanged() {
    // 获取样本表格的选择模型
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    // 获取选择的索引列表
    QModelIndexList indexList = selection->selectedIndexes();
    int count;
    foreach(QModelIndex index, indexList) {
        int row = index.row();
        int column = index.column();
        count = column * 8 + row;


        // 替换下面的代码
        for (int k = 0; k < 20; k++) {
            if (reactionPlate.targetList[count][k].name == view->ui->targetComboBox->currentText()) {
                reactionPlate.targetList[count][k].type = view->ui->typeComboBox->currentText();
                if (view->ui->countLineEdit->text() != "") {
                    reactionPlate.targetList[count][k].quantity = view->ui->countLineEdit->text();
                } else {
                    reactionPlate.targetList[count][k].quantity = "";
                }
            }
        }

        // 修改数据后不更新靶基因列表
        // 获取弹窗靶基因的索引
        //        int in = view->ui->targetComboBox->currentIndex();
        //        reactionPlate.targetList[count][in].type = view->ui->typeComboBox->currentText();
        //        LOG << "count :" << count <<  " in: " << in;
        //        if (view->ui->countLineEdit->text() != "") {
        //            reactionPlate.targetList[count][in].quantity = view->ui->countLineEdit->text();
        //        } else {
        //            reactionPlate.targetList[count][in].quantity = "";
        //        }

        // 最开始的代码
        //        for (int i = 0; i < 20; i++) {
        //            // 如果靶基因的名称和用户界面上的选择相同
        //            if (reactionPlate.targetList[count][i].name == view->ui->targetComboBox->currentText()) {
        //                // 更新目标报告基因的类型，根据用户界面上的选择
        //                targetListInfo[in][4] = view->ui->typeComboBox->currentText();
        //                reactionPlate.targetList[count][i].type = view->ui->typeComboBox->currentText();
        //                // 如果用户界面上有输入数量
        //                if (view->ui->countLineEdit->text() != "") {
        //                    // 更新目标报告基因的数量，根据用户界面上的输入
        //                    targetListInfo[in][5] = view->ui->countLineEdit->text();
        //                    reactionPlate.targetList[count][i].quantity = view->ui->countLineEdit->text();
        //                } else {
        //                    // 清空目标报告基因的数量
        //                    targetListInfo[in][5] = "";
        //                    reactionPlate.targetList[count][i].quantity = "";
        //                }
        //            }
        //        }

    }
    // 修改数据后不更新靶基因列表
    // targetInfoRenderTargetList();
    // 添加 更新反应板下方数据
    markTable();
}

/* 详情列表 */
void ExperimentPlateUi::detailTableInfoRender() {
    ui->detailTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);

    QList<QString> reporterBox;
    QList<QString> quencherBox;

    for (int l = 0; l < dyeFromConfig.length(); l++) {
        if (dyeFromConfig[l]["type"] == "报告基因") {
            reporterBox.append(dyeFromConfig[l]["name"]);
        } else if (dyeFromConfig[l]["type"] == "淬火基因") {
            quencherBox.append(dyeFromConfig[l]["name"]);
        }
    }

    if (ui->targetList->rowCount() > 0) {
        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, 0, 3);
        reporterBox.clear();
        for (int i = 0; i < combo_reporter->count(); i++) {
            reporterBox.append(combo_reporter->itemText(i));
        }
    }


    /* 根据配置文件获取行列数 */
    int row = sampleTableRowColumn[0];
    int column = sampleTableRowColumn[1];
    int allRow = reporterBox.length() * column * row;
    ui->detailTable->setRowCount(allRow);

    for (int l = 0; l < column * row; l++) {
        int acolumn = l / row;
        int arow = l % row;
        for (int i = 0; i < detailReporterBox.length(); i++) {
            // 调用createItem()函数创建一个表格项
            QTableWidgetItem *item = createItem(arow, acolumn);
            ui->detailTable->setItem(l * detailReporterBox.length() + i, 0, item);
        }
    }

    /* 清空detailTabl数据 */
    for (int l = 0; l < allRow; l++) {
        ui->detailTable->takeItem(l, 1);
        ui->detailTable->takeItem(l, 2);
        ui->detailTable->takeItem(l, 3);
        ui->detailTable->takeItem(l, 4);
        ui->detailTable->takeItem(l, 5);
    }

    /* 渲染detailTable */
    for (int l = 0; l < column * row; l++) {
        for (int i = 0; i < reporterBox.length(); i++) {
            //             if(reactionPlate.targetList[l][i].name == "null"){
            //                 break;
            //             }
            if (reactionPlate.sampleList[l].name != "null") {
                QTableWidgetItem *name = new QTableWidgetItem(reactionPlate.sampleList[l].name);
                ui->detailTable->setItem(l * reporterBox.length() + i, 1, name);
            }
            if (reactionPlate.targetList[l][i].name != "null") {
                QTableWidgetItem *name = new QTableWidgetItem(reactionPlate.targetList[l][i].name);
                ui->detailTable->setItem(l * reporterBox.length() + i, 2, name);
            }
            if (reactionPlate.targetList[l][i].type != "null") {
                QTableWidgetItem *type = new QTableWidgetItem(reactionPlate.targetList[l][i].type);
                ui->detailTable->setItem(l * reporterBox.length() + i, 3, type);
            }
            if (reactionPlate.targetList[l][i].quantity != "null") {
                QTableWidgetItem *quantity = new QTableWidgetItem(reactionPlate.targetList[l][i].quantity);
                ui->detailTable->setItem(l * reporterBox.length() + i, 4, quantity);
            }
            if (reactionPlate.targetList[l][i].explain != "null") {
                QTableWidgetItem *explain = new QTableWidgetItem(reactionPlate.targetList[l][i].explain);
                ui->detailTable->setItem(l * reporterBox.length() + i, 5, explain);
            }
        }
    }
    ui->detailTable->resizeRowsToContents();
    ui->detailTable->resizeColumnsToContents();
    ui->detailTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->detailTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
    ui->detailTable->setColumnWidth(0, 20);
}

/* 快速设置：靶基因全选功能 */
void ExperimentPlateUi::allSelectTarget() {
    // 定义一个整型变量renderFlag，初始值为0，用来标记是否需要渲染
    int renderFlag = 0;

    // 创建一个QItemSelectionModel对象，用来获取sampleTable的选中项
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    // 创建一个QModelIndexList对象，用来存储选中项的索引
    QModelIndexList indexList = selection->selectedIndexes();

    foreach(QModelIndex index, indexList) {
        // 定义一个整型变量a，初始值为0，用来标记是否有重复的靶基因或报告基因
        int a = 0;
        widgetLabel = createLabelWidget();

        // 获取索引所在的行数和列数
        int row = index.row();
        int column = index.column();

        int count = 8 * column + row;
        for (int in = 0; in < ui->target->count(); in++) {
            for (int l = 0; l < 20; l++) {
                if (reactionPlate.targetList[count][l].reporter != "null") {
                    // 获取靶基因列表中第in行第3列的单元格控件，它是一个QComboBox对象
                    QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, in, 3);
                    // 获取下拉框控件的当前文本
                    QString string_reporter = combo_reporter->currentText();
                    // 如果子项的名称和下拉框控件的当前文本相同，表示有相同的靶基因
                    if (reactionPlate.targetList[count][l].name == ui->target->itemText(in)) {
                        // 如果a为0，表示第一次发现重复
                        if (a == 0) {
                            cusMsg->show(this, CMsg::CWarning, "提示", "已存在相同靶基因，无法全选");
                            // 把renderFlag设为1，表示需要渲染
                            renderFlag = 1;
                            a++;
                        }
                        break;
                    }
                    // 如果子项的报告基因和下拉框控件的当前文本相同，表示有相同的报告基因
                    if (reactionPlate.targetList[count][l].reporter == string_reporter) {
                        // 如果a为0，表示第一次发现重复
                        if (a == 0) {
                            cusMsg->show(this, CMsg::CWarning, "提示", "已存在相同报告基因，无法全选");
                            renderFlag = 1;
                            a++;
                        }
                        break;
                    }
                }
            }
            if (a > 0) { break; }
        }
        if (a > 0) { break; }

    }


    // 如果renderFlag为0，表示没有发现重复的靶基因或报告基因
    if (renderFlag == 0) {
        for (int m = ui->targetList->rowCount() - 1; m > 0; m--) {
            // 获取第m行第3列的单元格控件，它是一个QComboBox对象
            QComboBox *combo_reporter1 = getComboBoxFromTable(ui->targetList, m, 3);
            // 获取下拉框控件的当前文本
            QString string_reporter1 = combo_reporter1->currentText();
            for (int n = m - 1; n >= 0; n--) {
                // 获取第n行第3列的单元格控件，它是一个QComboBox对象
                QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, n, 3);
                QString string_reporter = combo_reporter->currentText();

                // 如果两个下拉框控件的当前文本相同，表示有重复的报告基因
                if (string_reporter == string_reporter1) {
                    // 把renderFlag设为1，表示需要渲染
                    renderFlag = 1;
                    cusMsg->show(this, CMsg::CWarning, "提示", "全选失败，报告基因重复");
                    break;
                }

            }
            // 如果renderFlag为1，表示已经发现重复，跳出循环
            if (renderFlag == 1) { break; }
        }
    }


    // 如果renderFlag为0，表示没有发现重复的靶基因或报告基因
    if (renderFlag == 0) {
        // 创建一个QItemSelectionModel对象，用来获取sampleTable的选中项
        QItemSelectionModel *selection = ui->sampleTable->selectionModel();
        QModelIndexList indexList = selection->selectedIndexes();
        foreach(QModelIndex index, indexList) {
            // 创建一个显示标签的控件
            widgetLabel = createLabelWidget();
            int row = index.row();
            int column = index.column();

            int count = 8 * column + row;
            for (int in = 0; in < ui->target->count(); in++) {
                // 如果靶基因列表中第in行第2列的单元格为空或者没有文本，就把对应位置的名称设为"null"
                if (ui->targetList->item(in, 2) == nullptr || ui->targetList->item(in, 2)->text().isEmpty()) {
                    reactionPlate.targetList[count][in].name = "null";
                } else {
                    reactionPlate.targetList[count][in].name = ui->targetList->item(in, 2)->text();
                }
                // 获取靶基因列表中第in行第3列的单元格控件，它是一个QComboBox对象
                QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, in, 3);
                // 获取下拉框控件的当前文本
                QString string_reporter = combo_reporter->currentText();
                // 把靶基因列表中中对应位置的报告基因设为下拉框控件的当前文本
                reactionPlate.targetList[count][in].reporter = string_reporter;

                // 获取靶基因列表中第in行第4列的单元格控件，它是一个QComboBox对象
                QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, in, 4);
                // 获取下拉框控件的当前文本
                QString string_quencher = combo_quencher->currentText();
                // 把靶基因列表中对应位置的淬灭基因设为下拉框控件的当前文本
                reactionPlate.targetList[count][in].quencher = string_quencher;


                QComboBox *combo_type = getComboBoxFromTable(ui->targetList, in, 5);
                QString string_type = combo_type->currentText();
                // 把靶基因列表中对应位置的类型设为下拉框控件的当前文本
                reactionPlate.targetList[count][in].type = string_type;

                // 如果靶基因列表中第in行第6列的单元格为空或者没有文本，就把对应位置的数量设为"null"
                if (ui->targetList->item(in, 6) == nullptr || ui->targetList->item(in, 6)->text().isEmpty()) {
                    reactionPlate.targetList[count][in].quantity = "null";
                } else {
                    reactionPlate.targetList[count][in].quantity = ui->targetList->item(in, 6)->text();
                }

                if (ui->targetList->item(in, 7) == nullptr || ui->targetList->item(in, 7)->text().isEmpty()) {
                    reactionPlate.targetList[count][in].explain = "null";
                } else {
                    reactionPlate.targetList[count][in].explain = ui->targetList->item(in, 7)->text();
                }

                // 获取靶基因列表中第in行第1列的单元格的背景颜色
                QColor col = ui->targetList->item(in, 1)->backgroundColor();
                // 把颜色转换为字符串
                reactionPlate.targetList[count][in].color = colorTostring(col);
            }
            // 遍历靶基因下拉框的剩余的选项
            for (int in = ui->target->count(); in < 20; in++) {
                // 将靶基因列表中对应位置的子项的所有属性设为"null"
                reactionPlate.targetList[count][in].name = "null";
                reactionPlate.targetList[count][in].reporter = "null";
                reactionPlate.targetList[count][in].quencher = "null";
                reactionPlate.targetList[count][in].type = "null";
                reactionPlate.targetList[count][in].quantity = "null";
                reactionPlate.targetList[count][in].color = "null";
                reactionPlate.targetList[count][in].explain = "null";
            }

            // 如果样本列表中的当前位置的名称不为空
            if (reactionPlate.sampleList[count].name != "null") {
                // 如果查看菜单中第1个动作的提示文本为"样本名称"，且第1个和第3个动作都被选中
                if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                        ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                        ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                    // 获取样本列表中的当前位置的名称
                    QString name = reactionPlate.sampleList[count].name;
                    if (copySampleName[count] != "") {
                        name = copySampleName[count];
                    }
                    QLabel *label = createLabel(name);
                    // 获取样本列表中的当前位置的颜色值，它是一个字符串
                    QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                    QString mRgbStr = QString::number(color.rgb(), 16);
                    widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                    // 把标签控件添加到垂直布局中
                    vLayout->addWidget(label);
                }
                // 如果查看菜单中第1个动作的提示文本为"样本名称"，且第1个动作被选中，而第3个动作没有被选中
                if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                        ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                        !ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                    // 获取样本列表中的当前位置的名称
                    QString name = reactionPlate.sampleList[count].name;

                    if (name != "null") {
                        //  如果copySampleName数组中对应位置的字符串不为空，就把name设为该字符串
                        if (copySampleName[count] != "") {
                            name = copySampleName[count];
                        }
                        // 调用createLabel函数，传入样本名称作为参数，得到一个标签对象
                        QLabel *label = createLabel(name);
                        // 将标签添加到垂直布局中
                        vLayout->addWidget(label);
                    }
                }
                // 如果查看菜单中第1个动作的提示文本为"样本名称"，且第1个动作没有被选中，而第3个动作被选中
                if (ui->tableFilter->menu()->actions().value(0)->toolTip() == "样本名称" &&
                        ui->tableFilter->menu()->actions().value(0)->isChecked() &&
                        ui->tableFilter->menu()->actions().value(2)->isChecked()) {
                    QString name = reactionPlate.sampleList[count].name;

                    if (name != "null") {
                        if (copySampleName[count] != "") {
                            name = copySampleName[count];
                        }
                        // 创建一个QLabel对象，用来显示样本颜色
                        auto *label = new QLabel();
                        // 获取样本列表中的当前位置的颜色值，它是一个字符串
                        QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                        QString mRgbStr = QString::number(color.rgb(), 16);
                        widgetLabel->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
                        vLayout->addWidget(label);
                    }
                }
            }

            int p = 0;
            for (int l = 0; l < 20; l++) {
                // 如果查看菜单中第2个动作的提示文本为"靶基因"，且被选中
                if (ui->tableFilter->menu()->actions().value(1)->toolTip() == "靶基因" &&
                        ui->tableFilter->menu()->actions().value(1)->isChecked()) {
                    if (reactionPlate.targetList[count][l].reporter != "null") {
                        createTargetLabel(reactionPlate, count, l, p, false);
                    }
                }
            }
            // 设置网格布局的边距为0
            gLayout->setMargin(0);
            // 设置网格布局的间距为0
            gLayout->setSpacing(0);
            // 把网格布局添加到垂直布局中
            vLayout->addLayout(gLayout);
            // 把标签控件的父控件widgetLabel添加到ui中的sampleTable表格中对应的单元格中
            ui->sampleTable->setCellWidget(row, column, widgetLabel);
        }
    }

    markTable();
    renderDetailTable();
}

/* 渲染样本孔 */
void ExperimentPlateUi::renderMaterial() {
    // 耗材配型判断显示图片
    if (ui->materialType->currentIndex() == 0) { // 芯片-16
        // 遍历widget_4(管式-16) size() = 17 , children[0] 是 materialCircle16
        for (int i = 0; i < ui->widget_4->children().size(); i++) {
            if (ui->widget_4->children().at(i)->objectName() !=
                    "materialCircle16") { // widget_4中除了materialCircle16的都是按钮
                auto *button = qobject_cast<QPushButton *>(ui->widget_4->children().at(i)); // 将QObject转换为QPushButton

                LOG << "buttonobjectName" << button->objectName();

                if (button) { // 如果转换成功
                    button->setEnabled(false);
                    button->setStyleSheet(
                                "QPushButton {\ color: #fff;\ font-weight: bold;\ font-family: \"Alibaba PuHuiTi\";\ background: #9d9d9d;\ border-radius: 7px;\ }");
                    for (int l = 0; l < 20; l++) {
                        if (reactionPlate.targetList[i - 1][l].name != "null" ||
                                reactionPlate.sampleList[i - 1].name != "null") {
                            button->setEnabled(true); // 调用setEnabled方法
                            button->setStyleSheet(
                                        "QPushButton {\ color: #fff;\ font-weight: bold;\ font-family: \"Alibaba PuHuiTi\";\ background: #ba38f5;\ border-radius: 7px;\ }");
                        }
                    }
                }
            }
        }
        ui->materialTable->show();
    } else {
        // 遍历widget_5(管式) size() = 33, children[0] 是 materialCircle32)
        for (int i = 0; i < ui->widget_5->children().size(); i++) {
            if (ui->widget_5->children().at(i)->objectName() != "materialCircle32") {
                auto *button = qobject_cast<QPushButton *>(ui->widget_5->children().at(i)); // 将QObject转换为QPushButton
                if (button) { // 如果转换成功
                    button->setEnabled(false);
                    button->setStyleSheet(
                                "QPushButton {\ color: #fff;\ font-weight: bold;\ font-family: \"Alibaba PuHuiTi\";\ background: #9d9d9d;\ border-radius: 7px;\ }");
                    for (int l = 0; l < 20; l++) {
                        if (reactionPlate.targetList[i - 1][l].name != "null" ||
                                reactionPlate.sampleList[i - 1].name != "null") {
                            button->setEnabled(true); // 调用setEnabled方法
                            button->setStyleSheet(
                                        "QPushButton {\ color: #fff;\ font-weight: bold;\ font-family: \"Alibaba PuHuiTi\";\ background: #ba38f5;\ border-radius: 7px;\ }");
                        }
                    }
                }
            }
        }
        ui->matetialTable_1->show();
    }
}


/* 显示工具提示 */
void ExperimentPlateUi::ShowTooltip(QModelIndex index) {
    normalIndex = index;

    int count = 8 * index.column() + index.row();
    // 在单元格中找到所有的QLabel子控件，存入一个列表
    QList<QLabel *> labels = ui->sampleTable->cellWidget(index.row(), index.column())->findChildren<QLabel *>();

    QString data = "";
    for (int l = 0; l < 20; l++) {
        if (reactionPlate.targetList[count][l].name != "null") {
            data += reactionPlate.targetList[count][l].name;
            data += " ";
        }
    }

    // 在鼠标位置显示工具提示，内容为字符串data
    QToolTip::showText(QCursor::pos(), data);

    // 给每个QLabel子控件设置工具提示为data
    for (int l = 0; l < labels.count(); l++) {
        labels.at(l)->setToolTip(data);
    }
    // 如果有子控件，也给容器元素设置工具提示为data
    if (!labels.empty()) {
        /* 容器元素也加上toolTip */
        ui->sampleTable->cellWidget(index.row(), index.column())->setToolTip(data);
    }
}

/* 按下delete键清空孔位中的信息 */
void ExperimentPlateUi::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Delete) {
        clearTable();
    }
}

/* package该函数用于创建一个显示标签的控件 */
QWidget *ExperimentPlateUi::createLabelWidget() {
    // 创建一个垂直布局对象
    vLayout = new QVBoxLayout();
    // 创建一个QWidget对象，用来显示标签
    widgetLabel = new QWidget();
    // 创建一个网格布局对象
    gLayout = new QGridLayout();
    // 把垂直布局设置为标签控件的布局
    widgetLabel->setLayout(vLayout);
    // 返回创建好的控件
    return widgetLabel;
}

/* package创建表格项 */
QTableWidgetItem *ExperimentPlateUi::createItem(int arow, int acolumn) {
    // 根据arow的值获取对应的标签
    QString label = rowLetters[arow];
    // 拼接aitem
    QString aitem = QString("%1%2").arg(label).arg(acolumn + 1);
    // 创建一个表格项
    auto *item = new QTableWidgetItem(aitem);
    // 返回创建好的表格项
    return item;
}


/* package 设置反应板样式 */
QLabel *ExperimentPlateUi::createLabel(const QString &text) {
    // 创建一个标签对象
    auto *label = new QLabel();
    // 设置标签的文本为参数
    label->setText(text);
    // 创建一个字体对象
    QFont font;
    // 定义字体的名称和大小为常量
    const QString FONT_FAMILY = "Alibaba PuHuiTi";
    const int FONT_SIZE = 7;
    // 设置字体为阿里巴巴普惠体，大小为7
    font.setFamily(FONT_FAMILY);
    font.setPointSize(FONT_SIZE);
    // 设置标签的字体
    label->setFont(font);
    // 设置标签的对齐方式为水平居中和垂直居中
    label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    // 返回标签对象
    return label;
}

// 清空反应板信息
void ExperimentPlateUi::clearPlateInformation() {
    for (int m = 0; m < 96; m++) {
        reactionPlate.sampleList[m].name = "null";
        reactionPlate.sampleList[m].color_value = "null";
        reactionPlate.sampleList[m].remarks = "null";
        for (int n = 0; n < 20; n++) {
            reactionPlate.targetList[m][n].name = "null";
            reactionPlate.targetList[m][n].reporter = "null";
            reactionPlate.targetList[m][n].quencher = "null";
            reactionPlate.targetList[m][n].type = "null";
            reactionPlate.targetList[m][n].quantity = "null";
            reactionPlate.targetList[m][n].color = "null";
            reactionPlate.targetList[m][n].explain = "null";
        }
    }
}

/* 三元运算符，如果horizontal为真，就返回column，否则返回row */
void ExperimentPlateUi::fillStandIndex(int *standIndex, int row, int column, bool horizontal) {
    int addCount = 0;
    bool isDone = false;
    for (int m = 0; m < (horizontal ? column : row); m++) {
        for (int n = 0; n < (horizontal ? row : column); n++) {
            standIndex[(horizontal ? m * 8 + n : n * 8 + m)] = 1;
            addCount++;
            if (addCount >= stand->standCount) {
                isDone = true;
                break;
            }
        }
        if (isDone) {
            break;
        }
    }
}

/**
 * 对重复的操作进行封装
 * @param  row 行数
 * @param column 列数
 * @param horizontal bool, 如果是真则先遍历column
 * @param hasLetters 是否声明标签
 * @param hasWidgetLabel 是否设置布局
 * @param hasReporterLabel 是否设置反应板报告基因
 * @param shouldSetStandTargetReporter 是否设置标准品报告基因
 * @param shouldSetCellWidget 是否设置孔位控件
 * @param hasUtil 设置反应板报告基因的选择
*/
void ExperimentPlateUi::setStandLayout(int row, int column, bool horizontal, bool hasLetters, bool hasWidgetLabel,
                                       bool hasReporterLabel, bool shouldSetStandTargetReporter,
                                       bool shouldSetCellWidget, bool hasUtil) {
    if (hasLetters) {
        str = "";
    }
    int addCount = 0; // 遍历次数
    bool isDone = false; // 跳出循环标志
    for (int m = 0; m < (horizontal ? column : row); m++) {
        for (int n = 0; n < (horizontal ? row : column); n++) {
            if (hasWidgetLabel) {
                // 设置布局
                widgetLabel = createLabelWidget();
            }
            if (hasReporterLabel) {
                // 设置反应板报告基因
                createAndAddReporterLabel();
            }
            if (shouldSetStandTargetReporter) {
                // 设置反应板报告基因
                hasUtil ? addLabelsUntilNull(vLayout) : addLabelsAll(vLayout);
            }
            if (hasLetters) {
                QString label = rowLetters[horizontal ? n : m];
                str += QString("1%2%").arg(label).arg(horizontal ? m + 1 : n + 1);
            }

            addCount++;

            if (shouldSetCellWidget) {
                // 设置反应板孔位
                stand->ui->tableWidget->setCellWidget((horizontal ? n : m), (horizontal ? m : n), widgetLabel);
            }

            // 遍历次数达到设置的孔位数，跳出循环
            if (addCount >= stand->standCount) {
                isDone = true; // 跳出循环标志
                break;
            }
        }
        // 跳出循环
        if (isDone) {
            break;
        }
    }
}

/* 设置反应板报告基因 */
void ExperimentPlateUi::addLabelsUntilNull(QVBoxLayout *vLayout) {
    for (int l = 0; l < standTargetReporter.length(); l++) {
        if (standTargetReporter[l] == "null") {
            break;
        }
        QString reporter = standTargetReporter[l];
        QLabel *label = new QLabel();
        label->setText(reporter);
        vLayout->addWidget(label);
    }
}

/* 设置反应板报告基因 */
void ExperimentPlateUi::addLabelsAll(QVBoxLayout *vLayout) {
    for (int l = 0; l < standTargetReporter.length(); l++) {
        QString reporter = standTargetReporter[l];
        QLabel *label = new QLabel();
        label->setText(reporter);
        vLayout->addWidget(label);
    }
}

/* 用来创建并添加标准品信息的标签 */
void ExperimentPlateUi::createAndAddReporterLabel() {
    if (!standTargetReporter.empty()) {
        QString reporter = standTargetReporter[0];
        QLabel *label = new QLabel();
        label->setText(reporter);
        vLayout->addWidget(label);
    }
}

/** 定义一个函数，根据反应板的目标列表和计数器创建一个标签，并添加到反应板中
 *  @param reactionPlate        反应板
 *  @param count                反应板孔位序号
 *  @param l                    反应板该孔位靶基因的序号
 *  @param p                    临时变量
 *  @param whetherAlignCenter   是否居中 这个参数需要设置false，否则导致标签大小发生变化
 */
void ExperimentPlateUi::createTargetLabel(ReactionPlate &reactionPlate, int count, int l, int &p, bool whetherAlignCenter) {
    // 获取反应板的列表中第count个样本的第l个靶基因的报告基因
    QString reporter = reactionPlate.targetList[count][l].type;

//    LOG << "createTargetLabel" << reactionPlate.targetList[count][l].reporter << reporter;

    // 如果类型是"unknown(未知)"，则在报告基因前加上"U "
    if (reporter.contains("unknown(未知)")
            || reporter.contains("Unknown(未知)")
            || reporter.contains("未知")) { reporter = "U " + reactionPlate.targetList[count][l].reporter; }
    // 如果类型是"stander(标准)"，则在报告基因前加上"S "
    if (reporter.contains("stander(标准)")
            || reporter.contains("Stander(标准)")
            || reporter.contains("标准")) { reporter = "S " + reactionPlate.targetList[count][l].reporter; }
    // 如果类型是"NTC"，则在报告基因前加上"N "
    if (reporter == "NTC") { reporter = "N " + reactionPlate.targetList[count][l].reporter; }

    QLabel *label = createLabel(reporter);
    labelPtr = label;
    // 获取反应板的目标列表中第count个样本的第l个目标的颜色，并转换为QColor对象
    QColor color = stringToColor(reactionPlate.targetList[count][l].color);
    // 从QColor对象中提取RGB颜色值，并转换为QRgb对象
    QRgb rgbColor = qRgb(color.red(), color.green(), color.blue());
    // 将QRgb对象转换为十六进制字符串
    QString mRgbStr = QString::number(rgbColor, 16);
    // 设置标签的边框颜色为目标的颜色值
    label->setStyleSheet("QLabel{border:2px solid #" + mRgbStr + ";}");
    // 根据标签的文本长度和字体大小调整标签的大小，高度固定为22
    label->resize(static_cast<int>(strlen(reinterpret_cast<char *>(label->text().data()))) * label->font().pointSize(),
                  24);
    label->setFixedHeight(22);
    // 将标签添加到反应板中，位置由p决定
    if (whetherAlignCenter) {
        gLayout->addWidget(label, p / 10, p % 10, Qt::AlignCenter);
    } else {
        gLayout->addWidget(label, p / 10, p % 10);
    }
    // p自增1
    p++;
}

// 标准品反应板代码处理
void ExperimentPlateUi::handlerStandPlate(int count, int ccount) {
    for (int l = 0; l < ui->targetList->rowCount(); l++) {
        for (int k = 0; k < standTargetName.length(); k++) {
            // 如果标准板的目标名称和目标列表的名称相同
            if (standTargetName[k] == ui->targetList->item(l, 2)->text()) {
                for (int u = 0; u < 20; u++) {
                    // 如果反应板上的目标名称为空
                    if (reactionPlate.targetList[ccount][u].name == "null") {
                        // 如果目标列表中的名称为空或者没有文本
                        if (ui->targetList->item(l, 2) == nullptr || ui->targetList->item(l, 2)->text().isEmpty()) {
                            // 设置反应板上的目标名称为空
                            reactionPlate.targetList[ccount][u].name = "null";
                        } else {
                            // 否则获取目标列表中的名称作为反应板上的目标名称
                            reactionPlate.targetList[ccount][u].name = ui->targetList->item(l, 2)->text();
                        }
                        // 获取目标列表中的报告者组件
                        QComboBox *combo_reporter = getComboBoxFromTable(ui->targetList, l, 3);
                        // 获取报告者组件中的文本作为反应板上的报告者
                        QString string_reporter = combo_reporter->currentText();
                        reactionPlate.targetList[ccount][u].reporter = string_reporter;

                        // 获取目标列表(靶基因列表）中的淬灭基因组件
                        QComboBox *combo_quencher = getComboBoxFromTable(ui->targetList, l, 4);
                        // 获取淬灭基因组件中的文本作为反应板上的淬灭基因
                        QString string_quencher = combo_quencher->currentText();
                        reactionPlate.targetList[ccount][u].quencher = string_quencher;

                        // 获取目标列表中的类型组件
                        QComboBox *combo_type = getComboBoxFromTable(ui->targetList, l, 5);
                        // 获取类型组件中的文本作为反应板上的类型
                        QString string_type = combo_type->currentText();
                        reactionPlate.targetList[ccount][u].type = string_type;

                        if (ui->targetList->item(l, 6) == nullptr ||
                                ui->targetList->item(l, 6)->text().isEmpty()) {
                            reactionPlate.targetList[ccount][u].quantity = "null";
                        } else {
                            reactionPlate.targetList[ccount][u].quantity = ui->targetList->item(l, 6)->text();
                        }

                        // 如果目标列表中的说明为空或者没有文本
                        if (ui->targetList->item(l, 7) == nullptr ||
                                ui->targetList->item(l, 7)->text().isEmpty()) {
                            // 设置反应板上的数量为空
                            reactionPlate.targetList[ccount][u].explain = "null";
                        } else {
                            // 否则获取目标列表中的数量作为反应板上的数量
                            reactionPlate.targetList[ccount][u].explain = ui->targetList->item(l, 7)->text();
                        }

                        QColor col = ui->targetList->item(l, 1)->backgroundColor();
                        reactionPlate.targetList[count][u].color = colorTostring(col);
                        break;
                    }
                }
            }
        }
    }
}

/* 实验初始化时隐藏一些组件 */
void ExperimentPlateUi::hideComponents() {
    ui->detailTable->hide();
    ui->materialTable->hide();
    ui->matetialTable_1->hide();
    ui->extendSampleList->hide();
    ui->extendTargetList->hide();
    ui->restore->hide();
    ui->gotoTable->hide();
    ui->normalScreen->hide();
}

/* 实验初始化时实例化一些对象 */
void ExperimentPlateUi::createObjects() {
    dyeLibrary = new DyeLibrary();
    sampleLibrary = new SampleLibrary();
    //    samW = new SampleWidget();
    //    tarW = new TargetWidget();
    view = new doubleClicked();
    dyeLibrary = new DyeLibrary();
    sampleLibrary = new SampleLibrary();
    vLayout = new QVBoxLayout();
    widgetLabel = new QWidget();
    gLayout = new QGridLayout();
    sampleEdit = new QLineEdit();
    stand = new standard();
    configService = new ConfigFileService();
    cusMsg = new CustomMessageBox();
}

/* 实验初始化时初始化一些数据 */
void ExperimentPlateUi::initData() {
    sampleTableRowColumn = (int *) malloc(sizeof(int) * 2);
    targetTypeFromConfig.clear();
    consumableFromConfig.clear();
    dyeFromConfig.clear();
    targetName.clear();
    allDyeInfos = dyeLibrary->show();

    spinBoxNum = ui->copyCount->value();

    /* 记录默认参比荧光 */
    canBi = ui->yingguangLine->currentText();
}

int ExperimentPlateUi::calculateTotalHoles() {
    int a = stand->ui->copyLine->text().toInt();
    int b = stand->ui->countLine->text().toInt();
    int totalHoles = a * b;
    return totalHoles;
}

/* 设置"选择的孔位"的文本 */
void ExperimentPlateUi::setChooseText(QString num, int totalHoles) {
    //判断材料类型
    if (num == "芯片-16") {
        stand->ui->choose->setText(QString::number(totalHoles) + "/16孔位被选择");
    } else if (num == "管式") {
        stand->ui->choose->setText(QString::number(totalHoles) + "/32孔位被选择");
    }
}

/* 用于从表格中获取下拉框控件 */
QComboBox *ExperimentPlateUi::getComboBoxFromTable(QTableWidget *table, int row, int column) {
    QWidget *widget = table->cellWidget(row, column); // 获取单元格的控件
    QComboBox *combo = dynamic_cast<QComboBox *>(widget); // 将其转换为下拉框类型
    return combo; // 返回下拉框指针，如果转换失败，返回空指针
}

/**
 * 选中sampleTable颜色加深
*/
void ExperimentPlateUi::slotChangeItemsColor() {
    QItemSelectionModel *selection = ui->sampleTable->selectionModel();
    QModelIndexList indexList = selection->selectedIndexes();
    int isCellHasColorAndSelected[32] = {0};
    foreach(QModelIndex index, indexList) {
        int row = index.row();
        int column = index.column();
        int count = column * 8 + row; // 易发生数组越界
        if (count < 32) {
            isCellHasColorAndSelected[count] = 1;
        }
    }
    // for (int i = 0; i < 32; i ++) {
    // LOG << i << " :" << isCellHasColorAndSelected[i] << " ";
    // }
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 4; j++) {
            int count = j * 8 + i;
            if (isCellHasColorAndSelected[count] != 1 && reactionPlate.sampleList[count].color_value != "null") {
                QWidget *widget = ui->sampleTable->cellWidget(i, j);
                QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
                QString mRgbStr = QString::number(color.rgb(), 16);
                widget->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
            }
        }
    }
    // 上面重新设置表格颜色为reactionPlate中的颜色，下面将选中的颜色加深
    foreach(QModelIndex index, indexList) {
        int row = index.row();
        int column = index.column();
        int count = column * 8 + row;
        QWidget *widget = ui->sampleTable->cellWidget(row, column);
        if (reactionPlate.sampleList[count].color_value != "null") {
            QColor color = stringToColor(reactionPlate.sampleList[count].color_value);
            color.setRed(color.red() * 0.7);
            color.setBlue(color.blue() * 0.7);
            color.setGreen(color.green() * 0.7);
            QString mRgbStr = QString::number(color.rgb(), 16);
            widget->setStyleSheet(QString("background-color: #%1").arg(mRgbStr));
            // widget->setStyleSheet(QString("background-color: rgb(123,123,123)"));
        }
    }
    // // 设置所有的下拉框为黑色字
    // for (int l = 0; l < ui->sample->count(); l++) {
    //     ui->sample->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    // }
    // for (int l = 0; l < ui->target->count(); l++) {
    //     ui->target->setItemData(l, QColor(Qt::black), Qt::ForegroundRole);
    // }
}

// void changeQuickSettingsTextColor() {
// }

/* 休眠函数 */
void ExperimentPlateUi::sleep(int msec){
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime)
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}


//** 高级设置类型数量不可点击 */
void ExperimentPlateUi::targetNumberNotClick() {
    for (int i = 0 ; i < ui->targetList->rowCount(); i ++ ) {
        ui->targetList->item(i, 6)->setFlags(ui->targetList->item(i, 6)->flags() & (~Qt::ItemIsEditable));
        ui->targetList->item(i, 7)->setFlags(ui->targetList->item(i, 7)->flags() & (~Qt::ItemIsEditable));
        auto *comboBox = qobject_cast<QComboBox *>(ui->targetList->cellWidget(i, 5));
        if (comboBox != nullptr)
        {
            comboBox->setEnabled(false);
        }
    }
}

// ** 高级设置类型数量可点击 */
void ExperimentPlateUi::targetNumberCanClick() {
    for (int i = 0 ; i < ui->targetList->rowCount(); i ++ ) {
        ui->targetList->item(i, 6)->setFlags(ui->targetList->item(i, 6)->flags() | Qt::ItemIsEditable);
        ui->targetList->item(i, 7)->setFlags(ui->targetList->item(i, 7)->flags() | Qt::ItemIsEditable);
        auto *comboBox = qobject_cast<QComboBox *>(ui->targetList->cellWidget(i, 5));
        if (comboBox != nullptr)
        {
            comboBox->setEnabled(true);
        }
    }
}